summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKhem Raj <kraj@mvista.com>2008-06-27 04:01:29 +0000
committerKhem Raj <kraj@mvista.com>2008-06-27 04:01:29 +0000
commitd3f9546960f56c05624e2932a899db7f1d38a480 (patch)
tree6c63cec6c57ad8060a4b6ef983b3b24ece5fc87c
parentda3e789d079c47fea519270269e0c63dd5d497e2 (diff)
downloaduClibc-alpine-d3f9546960f56c05624e2932a899db7f1d38a480.tar.bz2
uClibc-alpine-d3f9546960f56c05624e2932a899db7f1d38a480.tar.xz
Sync build machinery stuff from trunk. Some more fixed for mips nptl port
-rw-r--r--Makefile.in20
-rw-r--r--Makerules18
-rw-r--r--Rules.mak54
-rwxr-xr-xextra/scripts/gen_bits_syscall_h.sh10
-rwxr-xr-xextra/scripts/install_headers.sh58
-rwxr-xr-xextra/scripts/install_kernel_headers.sh74
-rw-r--r--extra/scripts/unifdef.c1005
-rw-r--r--include/libc-symbols.h93
-rw-r--r--include/string.h163
-rw-r--r--include/strings.h4
-rw-r--r--ldso/ldso/mips/elfinterp.c12
-rw-r--r--libc/inet/resolv.c1
-rw-r--r--libc/inet/rpc/ruserpass.c1
-rw-r--r--libc/misc/internals/tempname.c4
-rw-r--r--libc/misc/regex/regex.c1
-rw-r--r--libc/misc/time/time.c1
-rw-r--r--libc/misc/wchar/wchar.c1
-rw-r--r--libc/stdlib/realpath.c1
-rw-r--r--libc/sysdeps/linux/common/gethstnm.c37
-rw-r--r--libc/sysdeps/linux/mips/__syscall_error.c18
-rw-r--r--libc/sysdeps/linux/mips/clone.S1
-rw-r--r--libc/sysdeps/linux/mips/sys/asm.h15
-rw-r--r--libpthread/nptl/sysdeps/pthread/sigaction.c24
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch2
-rw-r--r--libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h9
25 files changed, 1467 insertions, 160 deletions
diff --git a/Makefile.in b/Makefile.in
index 8fbd45227..8d254722b 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -133,13 +133,19 @@ install: install_runtime install_dev
RUNTIME_PREFIX_LIB_FROM_DEVEL_PREFIX_LIB=$(shell $(top_srcdir)extra/scripts/relative_path.sh $(DEVEL_PREFIX)lib $(RUNTIME_PREFIX)lib)
+$(top_builddir)extra/scripts/unifdef: $(top_srcdir)extra/scripts/unifdef.c
+ $(hcompile.u)
+
+# Installs kernel header files (linux/*, asm/*, asm-generic/*).
+install_kernel_headers: headers
+ top_builddir=$(top_builddir) \
+ $(top_srcdir)extra/scripts/install_kernel_headers.sh include $(PREFIX)$(DEVEL_PREFIX)include
+
# Installs header files.
-install_headers: headers
+install_headers: headers $(top_builddir)extra/scripts/unifdef
$(INSTALL) -d $(PREFIX)$(DEVEL_PREFIX)include
- printf ".svn\n.cvsignore\nCVS\n" > tar_exclude ; \
- $(TAR) -chf - -X tar_exclude include \
- | $(TAR) -xf - -C $(PREFIX)$(DEVEL_PREFIX)
- rm -f tar_exclude
+ top_builddir=$(top_builddir) \
+ $(top_srcdir)extra/scripts/install_headers.sh include $(PREFIX)$(DEVEL_PREFIX)include
printf '#ifndef _LIBC_INTERNAL_H\n#define _LIBC_INTERNAL_H 1\n#endif\n' > \
$(PREFIX)$(DEVEL_PREFIX)include/libc-internal.h
echo '/* Dont use _syscall#() macros; use the syscall() function */' > \
@@ -230,10 +236,6 @@ ifeq ($(UCLIBC_HAS_THREADS_NATIVE),y)
# Remove this as it is only used internally.
$(RM) $(PREFIX)$(DEVEL_PREFIX)include/tls.h
endif
- -@for i in `find $(PREFIX)$(DEVEL_PREFIX)include -type d` ; do \
- chmod 755 $$i; chmod 644 $$i/*.h > /dev/null 2>&1; \
- done
- -chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$$/\1:\2/'` $(PREFIX)$(DEVEL_PREFIX)include
# Installs development library links.
install_dev: install_headers
diff --git a/Makerules b/Makerules
index b4df69bb6..aec7238a0 100644
--- a/Makerules
+++ b/Makerules
@@ -126,9 +126,9 @@ define link.so
$(Q)$(INSTALL) -d $(dir $@)
$(Q)$(RM) $@ $@.$(2) $(dir $@)$(1)
@$(disp_ld)
- $(Q)$(LD) $(LDFLAGS-$(notdir $@)) -soname=$(notdir $@).$(2) \
- -o $(dir $@)$(1) $(START_FILE-$(notdir $@)) \
- --whole-archive $(firstword $^) --no-whole-archive \
+ $(Q)$(CC) $(LDFLAGS-$(notdir $@)) -Wl,-soname=$(notdir $@).$(2) \
+ -nostdlib -o $(dir $@)$(1) $(START_FILE-$(notdir $@)) \
+ -Wl,--whole-archive $(firstword $^) -Wl,--no-whole-archive \
$(LIBS-$(notdir $@)) $(LIBGCC) $(END_FILE-$(notdir $@))
$(Q)$(LN) -sf $(1) $@.$(2)
$(Q)$(LN) -sf $(1) $@
@@ -150,10 +150,10 @@ define link-flat.so
$(Q)$(INSTALL) -d $(dir $@)
$(Q)$(RM) $(1) $@
@$(disp_ld)
- $(Q)$(LD) $(LDFLAGS-$(notdir $@)) -o $(1) \
- -elf2flt -shared-lib-id $(2) $(top_builddir)lib/Scrt1.o \
- $(top_builddir)/lib/crti.o --whole-archive $(firstword $^) \
- --no-whole-archive $(LIBS-$(notdir $@)) $(LIBGCC) \
+ $(Q)$(CC) $(LDFLAGS-$(notdir $@)) -nostdlib -o $(1) \
+ -Wl,-elf2flt -Wl,-shared-lib-id $(2) $(top_builddir)lib/Scrt1.o \
+ $(top_builddir)/lib/crti.o -Wl,--whole-archive $(firstword $^) \
+ -Wl,--no-whole-archive $(LIBS-$(notdir $@)) $(LIBGCC) \
$(top_builddir)/lib/crtn.o
endef
@@ -161,8 +161,8 @@ define linkm.so
$(Q)$(INSTALL) -d $(dir $@)
$(Q)$(RM) $@ $@.$(2) $(dir $@)$(1)
@$(disp_ld)
- $(Q)$(LD) $(LDFLAGS-$(notdir $@)) -soname=$(notdir $@).$(2) \
- -o $(dir $@)$(1) $(START_FILE-$(notdir $@)) $^ \
+ $(Q)$(CC) $(LDFLAGS-$(notdir $@)) -Wl,-soname=$(notdir $@).$(2) \
+ -nostdlib -o $(dir $@)$(1) $(START_FILE-$(notdir $@)) $^ \
$(LIBS-$(notdir $@)) $(LIBGCC) $(END_FILE-$(notdir $@))
$(Q)$(LN) -sf $(1) $@.$(2)
$(Q)$(LN) -sf $(1) $@
diff --git a/Rules.mak b/Rules.mak
index fe65bd7c2..336955e75 100644
--- a/Rules.mak
+++ b/Rules.mak
@@ -113,6 +113,9 @@ interp :=
ldso :=
endif
+comma:=,
+space:= #
+
ifndef CROSS
CROSS=$(subst ",, $(strip $(CROSS_COMPILER_PREFIX)))
endif
@@ -187,8 +190,8 @@ endif
ifeq ($(TARGET_ARCH),arm)
OPTIMIZATION+=-fstrict-aliasing
- CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-EL
- CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-EB
+ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL
+ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB
CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-mlittle-endian
CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mbig-endian
CPU_CFLAGS-$(CONFIG_GENERIC_ARM)+=
@@ -209,8 +212,8 @@ ifeq ($(TARGET_ARCH),arm)
endif
ifeq ($(TARGET_ARCH),mips)
- CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-EL
- CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-EB
+ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL
+ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB
CPU_CFLAGS-$(CONFIG_MIPS_ISA_1)+=-mips1
CPU_CFLAGS-$(CONFIG_MIPS_ISA_2)+=-mips2 -mtune=mips2
CPU_CFLAGS-$(CONFIG_MIPS_ISA_3)+=-mips3 -mtune=mips3
@@ -218,12 +221,12 @@ ifeq ($(TARGET_ARCH),mips)
CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS32)+=-mips32 -mtune=mips32
CPU_CFLAGS-$(CONFIG_MIPS_ISA_MIPS64)+=-mips64 -mtune=mips32
ifeq ($(strip $(ARCH_BIG_ENDIAN)),y)
- CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-melf64btsmip
- CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-melf32btsmip
+ CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64btsmip
+ CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32btsmip
endif
ifeq ($(strip $(ARCH_LITTLE_ENDIAN)),y)
- CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-melf64ltsmip
- CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-melf32ltsmip
+ CPU_LDFLAGS-$(CONFIG_MIPS_N64_ABI)+=-Wl,-melf64ltsmip
+ CPU_LDFLAGS-$(CONFIG_MIPS_O32_ABI)+=-Wl,-melf32ltsmip
endif
CPU_CFLAGS-$(CONFIG_MIPS_N64_ABI)+=-mabi=64
CPU_CFLAGS-$(CONFIG_MIPS_O32_ABI)+=-mabi=32
@@ -231,15 +234,15 @@ ifeq ($(TARGET_ARCH),mips)
endif
ifeq ($(TARGET_ARCH),nios)
- CPU_LDFLAGS-y+=-m32
- CPU_CFLAGS-y+=-m32
+ CPU_LDFLAGS-y+=-Wl,-m32
+ CPU_CFLAGS-y+=-Wl,-m32
endif
ifeq ($(TARGET_ARCH),sh)
OPTIMIZATION+=-fstrict-aliasing
OPTIMIZATION+= $(call check_gcc,-mprefergot,)
- CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-EL
- CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-EB
+ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN)+=-Wl,-EL
+ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN)+=-Wl,-EB
CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN)+=-ml
CPU_CFLAGS-$(ARCH_BIG_ENDIAN)+=-mb
CPU_CFLAGS-$(CONFIG_SH2)+=-m2
@@ -255,23 +258,23 @@ endif
ifeq ($(TARGET_ARCH),sh64)
OPTIMIZATION+=-fstrict-aliasing
- CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN):=-EL
- CPU_LDFLAGS-$(ARCH_BIG_ENDIAN):=-EB
+ CPU_LDFLAGS-$(ARCH_LITTLE_ENDIAN):=-Wl,-EL
+ CPU_LDFLAGS-$(ARCH_BIG_ENDIAN):=-Wl,-EB
CPU_CFLAGS-$(ARCH_LITTLE_ENDIAN):=-ml
CPU_CFLAGS-$(ARCH_BIG_ENDIAN):=-mb
CPU_CFLAGS-$(CONFIG_SH5)+=-m5-32media
endif
ifeq ($(TARGET_ARCH),h8300)
- CPU_LDFLAGS-$(CONFIG_H8300H)+= -ms8300h
- CPU_LDFLAGS-$(CONFIG_H8S) += -ms8300s
+ CPU_LDFLAGS-$(CONFIG_H8300H)+= -Wl,-ms8300h
+ CPU_LDFLAGS-$(CONFIG_H8S) += -Wl,-ms8300s
CPU_CFLAGS-$(CONFIG_H8300H) += -mh -mint32
CPU_CFLAGS-$(CONFIG_H8S) += -ms -mint32
endif
ifeq ($(TARGET_ARCH),cris)
- CPU_LDFLAGS-$(CONFIG_CRIS)+=-mcrislinux
- CPU_LDFLAGS-$(CONFIG_CRISV32)+=-mcrislinux
+ CPU_LDFLAGS-$(CONFIG_CRIS)+=-Wl,-mcrislinux
+ CPU_LDFLAGS-$(CONFIG_CRISV32)+=-Wl,-mcrislinux
CPU_CFLAGS-$(CONFIG_CRIS)+=-mlinux
PICFLAG:=-fpic
PIEFLAG_NAME:=-fpie
@@ -295,13 +298,13 @@ ifeq ($(TARGET_ARCH),powerpc)
endif
ifeq ($(TARGET_ARCH),frv)
- CPU_LDFLAGS-$(CONFIG_FRV)+=-melf32frvfd
+ CPU_LDFLAGS-$(CONFIG_FRV)+=-Wl,-melf32frvfd
# Using -pie causes the program to have an interpreter, which is
# forbidden, so we must make do with -shared. Unfortunately,
# -shared by itself would get us global function descriptors
# and calls through PLTs, dynamic resolution of symbols, etc,
# which would break as well, but -Bsymbolic comes to the rescue.
- export LDPIEFLAG:=-shared -Bsymbolic
+ export LDPIEFLAG:=-Wl,-shared -Wl,-Bsymbolic
UCLIBC_LDSO=ld.so.1
endif
@@ -396,16 +399,17 @@ endif
# only i386 is known to work if compile.S gets -D__ASSEMBLER__
#CFLAGS += $(call check_gcc,-std=c99,)
-LDFLAGS_NOSTRIP:=$(CPU_LDFLAGS-y) -shared --warn-common --warn-once -z combreloc
+LDFLAGS_NOSTRIP:=$(CPU_LDFLAGS-y) -Wl,-shared \
+ -Wl,--warn-common -Wl,--warn-once -Wl,-z,combreloc
# binutils-2.16.1 warns about ignored sections, 2.16.91.0.3 and newer are ok
#LDFLAGS_NOSTRIP+=$(call check_ld,--gc-sections)
ifeq ($(UCLIBC_BUILD_RELRO),y)
-LDFLAGS_NOSTRIP+=-z relro
+LDFLAGS_NOSTRIP+=-Wl,-z,relro
endif
ifeq ($(UCLIBC_BUILD_NOW),y)
-LDFLAGS_NOSTRIP+=-z now
+LDFLAGS_NOSTRIP+=-Wl,-z,now
endif
ifeq ($(LDSO_GNU_HASH_SUPPORT),y)
@@ -418,7 +422,7 @@ LDFLAGS_NOSTRIP += $(LDFLAGS_GNUHASH)
endif
endif
-LDFLAGS:=$(LDFLAGS_NOSTRIP) -z defs
+LDFLAGS:=$(LDFLAGS_NOSTRIP) -Wl,-z,defs
ifeq ($(DODEBUG),y)
#CFLAGS += -g3
@@ -427,7 +431,7 @@ else
CFLAGS += $(OPTIMIZATION) $(XARCH_CFLAGS) -DNDEBUG
endif
ifeq ($(DOSTRIP),y)
-LDFLAGS += -s
+LDFLAGS += -Wl,-s
else
STRIPTOOL := true -Stripping_disabled
endif
diff --git a/extra/scripts/gen_bits_syscall_h.sh b/extra/scripts/gen_bits_syscall_h.sh
index 116534ab3..c0b4c25f5 100755
--- a/extra/scripts/gen_bits_syscall_h.sh
+++ b/extra/scripts/gen_bits_syscall_h.sh
@@ -8,9 +8,10 @@
# June 27, 2001 Manuel Novoa III
#
-# This script expects top_builddir and CC (as used in the Makefiles) to be set in
-# the environment, and outputs the appropriate $top_builddir/include/bits/sysnum.h
-# corresponding to $top_builddir/include/asm/unistd.h to stdout.
+# This script expects top_builddir and CC (as used in the Makefiles) to be set
+# in the environment, and outputs the appropriate
+# $top_builddir/include/bits/sysnum.h # corresponding to
+# $top_builddir/include/asm/unistd.h to stdout.
#
# Warning!!! This does _no_ error checking!!!
@@ -28,7 +29,8 @@ esac
-e 's/^[ ]*#undef[ ]*__NR_\([A-Za-z0-9_]*\).*/UNDEFUCLIBC_\1 __NR_\1/gp' # needed to strip out any kernel-internal defines
) |
$CC -E $INCLUDE_OPTS - |
-( echo "/* WARNING!!! AUTO-GENERATED FILE!!! DO NOT EDIT!!! */" ; echo ;
+( echo "/* WARNING!!! AUTO-GENERATED FILE!!! DO NOT EDIT!!! */" ;
+ echo ;
echo "#ifndef _BITS_SYSNUM_H" ;
echo "#define _BITS_SYSNUM_H" ;
echo ;
diff --git a/extra/scripts/install_headers.sh b/extra/scripts/install_headers.sh
new file mode 100755
index 000000000..6d73ad2c6
--- /dev/null
+++ b/extra/scripts/install_headers.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# Parameters:
+# $1 = source dir
+# $2 = dst dir
+# $top_builddir = well you guessed it
+
+die_if_not_dir()
+{
+ for dir in "$@"; do
+ test -d "$dir" && continue
+ echo "Error: '$dir' is not a directory"
+ exit 1
+ done
+}
+
+
+# Ensure that created dirs/files have 755/644 perms
+umask 022
+
+
+# Sanity tests
+die_if_not_dir "$1"
+mkdir -p "$2" 2>/dev/null
+die_if_not_dir "$2"
+die_if_not_dir "$top_builddir"
+if ! test -x "$top_builddir/extra/scripts/unifdef"; then
+ echo "Error: need '$top_builddir/extra/scripts/unifdef' executable"
+ exit 1
+fi
+
+
+# Sanitize and copy uclibc headers
+(
+# We must cd, or else we'll prepend "$1" to filenames!
+cd "$1" || exit 1
+find ! -name '.' -a ! -path '*/.*'
+) | \
+(
+IFS=''
+while read -r filename; do
+ filename="${filename#./}"
+ if test -d "$1/$filename"; then
+ mkdir -p "$2/$filename" 2>/dev/null
+ else
+ # NB: unifdef exits with 1 if output is not
+ # exactly the same as input. That's ok.
+ # Do not abort the script if unifdef "fails"!
+ "$top_builddir/extra/scripts/unifdef" -UUCLIBC_INTERNAL "$1/$filename" \
+ | grep -v '^libc_hidden_proto[ ]*([a-zA-Z0-9_]*)$' >"$2/$filename"
+ fi
+done
+)
+
+
+# Fix mode/owner bits
+cd "$2" || exit 1
+chmod -R u=rwX,go=rX . >/dev/null 2>&1
+chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1
diff --git a/extra/scripts/install_kernel_headers.sh b/extra/scripts/install_kernel_headers.sh
new file mode 100755
index 000000000..7e86eb850
--- /dev/null
+++ b/extra/scripts/install_kernel_headers.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Parameters:
+# $1 = source dir
+# $2 = dst dir
+# $top_builddir = well you guessed it
+
+die_if_not_dir()
+{
+ for dir in "$@"; do
+ test -d "$dir" && continue
+ echo "Error: '$dir' is not a directory"
+ exit 1
+ done
+}
+
+
+# Ensure that created dirs/files have 755/644 perms
+umask 022
+
+
+# Sanity tests
+die_if_not_dir "$1"
+mkdir -p "$2" 2>/dev/null
+die_if_not_dir "$2"
+die_if_not_dir "$top_builddir"
+
+
+# Just copy (no sanitization) some kernel headers.
+eval `grep ^KERNEL_HEADERS "$top_builddir/.config"`
+if ! test "$KERNEL_HEADERS" \
+|| ! test -d "$KERNEL_HEADERS/asm" \
+|| ! test -d "$KERNEL_HEADERS/asm-generic" \
+|| ! test -d "$KERNEL_HEADERS/linux" \
+; then
+ echo "Error: '$KERNEL_HEADERS' is not a directory containing kernel headers."
+ echo "Check KERNEL_HEADERS= in your .config file."
+ exit 1
+fi
+# Do the copying only if src and dst dirs are not the same.
+# Be thorough: do not settle just for textual compare,
+# and guard against "pwd" being handled as shell builtin.
+# Double quoting looks weird, but it works (even bbox ash too).
+if test "`(cd "$KERNEL_HEADERS"; env pwd)`" != "`(cd "$2"; env pwd)`"; then
+ # NB: source or target files and directories may be symlinks,
+ # and for all we know, good reasons.
+ # We must work correctly in these cases. This includes "do not replace
+ # target symlink with real directory" rule. So, no rm -rf here please.
+ mkdir -p "$2/asm" 2>/dev/null
+ mkdir -p "$2/linux" 2>/dev/null
+ # Exists, but is not a dir? That's bad, bail out
+ die_if_not_dir "$2/asm" "$2/linux"
+ # cp -HL creates regular destination files even if sources are symlinks.
+ # This is intended.
+ # (NB: you need busybox 1.11.x for this. earlier ones are slightly buggy)
+ cp -RHL "$KERNEL_HEADERS/asm"/* "$2/asm" || exit 1
+ cp -RHL "$KERNEL_HEADERS/linux"/* "$2/linux" || exit 1
+ # Linux 2.4 doesn't have it
+ if test -d "$KERNEL_HEADERS/asm-generic"; then
+ mkdir -p "$2/asm-generic" 2>/dev/null
+ die_if_not_dir "$2/asm-generic"
+ cp -RHL "$KERNEL_HEADERS/asm-generic"/* "$2/asm-generic" || exit 1
+ fi
+ if ! test -f "$2/linux/version.h"; then
+ echo "Warning: '$KERNEL_HEADERS/linux/version.h' is not found"
+ echo "in kernel headers directory specified in .config."
+ echo "Some programs won't like that. Consider fixing it by hand."
+ fi
+fi
+
+
+# Fix mode/owner bits
+cd "$2" || exit 1
+chmod -R u=rwX,go=rX . >/dev/null 2>&1
+chown -R `id | sed 's/^uid=\([0-9]*\).*gid=\([0-9]*\).*$/\1:\2/'` . >/dev/null 2>&1
diff --git a/extra/scripts/unifdef.c b/extra/scripts/unifdef.c
new file mode 100644
index 000000000..552025e72
--- /dev/null
+++ b/extra/scripts/unifdef.c
@@ -0,0 +1,1005 @@
+/*
+ * Copyright (c) 2002 - 2005 Tony Finch <dot@dotat.at>. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by Dave Yost.
+ * It was rewritten to support ANSI C by Tony Finch. The original version of
+ * unifdef carried the following copyright notice. None of its code remains
+ * in this version (though some of the names remain).
+ *
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#ifndef lint
+#if 0
+static const char copyright[] =
+"@(#) Copyright (c) 1985, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif
+#ifdef __IDSTRING
+__IDSTRING(Berkeley, "@(#)unifdef.c 8.1 (Berkeley) 6/6/93");
+__IDSTRING(NetBSD, "$NetBSD: unifdef.c,v 1.8 2000/07/03 02:51:36 matt Exp $");
+__IDSTRING(dotat, "$dotat: things/unifdef.c,v 1.171 2005/03/08 12:38:48 fanf2 Exp $");
+#endif
+#endif /* not lint */
+#ifdef __FBSDID
+__FBSDID("$FreeBSD: /repoman/r/ncvs/src/usr.bin/unifdef/unifdef.c,v 1.20 2005/05/21 09:55:09 ru Exp $");
+#endif
+
+/*
+ * unifdef - remove ifdef'ed lines
+ *
+ * Wishlist:
+ * provide an option which will append the name of the
+ * appropriate symbol after #else's and #endif's
+ * provide an option which will check symbols after
+ * #else's and #endif's to see that they match their
+ * corresponding #ifdef or #ifndef
+ *
+ * The first two items above require better buffer handling, which would
+ * also make it possible to handle all "dodgy" directives correctly.
+ */
+
+#include <ctype.h>
+#include <err.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+size_t strlcpy(char *dst, const char *src, size_t siz);
+
+/* types of input lines: */
+typedef enum {
+ LT_TRUEI, /* a true #if with ignore flag */
+ LT_FALSEI, /* a false #if with ignore flag */
+ LT_IF, /* an unknown #if */
+ LT_TRUE, /* a true #if */
+ LT_FALSE, /* a false #if */
+ LT_ELIF, /* an unknown #elif */
+ LT_ELTRUE, /* a true #elif */
+ LT_ELFALSE, /* a false #elif */
+ LT_ELSE, /* #else */
+ LT_ENDIF, /* #endif */
+ LT_DODGY, /* flag: directive is not on one line */
+ LT_DODGY_LAST = LT_DODGY + LT_ENDIF,
+ LT_PLAIN, /* ordinary line */
+ LT_EOF, /* end of file */
+ LT_COUNT
+} Linetype;
+
+static char const * const linetype_name[] = {
+ "TRUEI", "FALSEI", "IF", "TRUE", "FALSE",
+ "ELIF", "ELTRUE", "ELFALSE", "ELSE", "ENDIF",
+ "DODGY TRUEI", "DODGY FALSEI",
+ "DODGY IF", "DODGY TRUE", "DODGY FALSE",
+ "DODGY ELIF", "DODGY ELTRUE", "DODGY ELFALSE",
+ "DODGY ELSE", "DODGY ENDIF",
+ "PLAIN", "EOF"
+};
+
+/* state of #if processing */
+typedef enum {
+ IS_OUTSIDE,
+ IS_FALSE_PREFIX, /* false #if followed by false #elifs */
+ IS_TRUE_PREFIX, /* first non-false #(el)if is true */
+ IS_PASS_MIDDLE, /* first non-false #(el)if is unknown */
+ IS_FALSE_MIDDLE, /* a false #elif after a pass state */
+ IS_TRUE_MIDDLE, /* a true #elif after a pass state */
+ IS_PASS_ELSE, /* an else after a pass state */
+ IS_FALSE_ELSE, /* an else after a true state */
+ IS_TRUE_ELSE, /* an else after only false states */
+ IS_FALSE_TRAILER, /* #elifs after a true are false */
+ IS_COUNT
+} Ifstate;
+
+static char const * const ifstate_name[] = {
+ "OUTSIDE", "FALSE_PREFIX", "TRUE_PREFIX",
+ "PASS_MIDDLE", "FALSE_MIDDLE", "TRUE_MIDDLE",
+ "PASS_ELSE", "FALSE_ELSE", "TRUE_ELSE",
+ "FALSE_TRAILER"
+};
+
+/* state of comment parser */
+typedef enum {
+ NO_COMMENT = false, /* outside a comment */
+ C_COMMENT, /* in a comment like this one */
+ CXX_COMMENT, /* between // and end of line */
+ STARTING_COMMENT, /* just after slash-backslash-newline */
+ FINISHING_COMMENT, /* star-backslash-newline in a C comment */
+ CHAR_LITERAL, /* inside '' */
+ STRING_LITERAL /* inside "" */
+} Comment_state;
+
+static char const * const comment_name[] = {
+ "NO", "C", "CXX", "STARTING", "FINISHING", "CHAR", "STRING"
+};
+
+/* state of preprocessor line parser */
+typedef enum {
+ LS_START, /* only space and comments on this line */
+ LS_HASH, /* only space, comments, and a hash */
+ LS_DIRTY /* this line can't be a preprocessor line */
+} Line_state;
+
+static char const * const linestate_name[] = {
+ "START", "HASH", "DIRTY"
+};
+
+/*
+ * Minimum translation limits from ISO/IEC 9899:1999 5.2.4.1
+ */
+#define MAXDEPTH 64 /* maximum #if nesting */
+#define MAXLINE 4096 /* maximum length of line */
+#define MAXSYMS 4096 /* maximum number of symbols */
+
+/*
+ * Sometimes when editing a keyword the replacement text is longer, so
+ * we leave some space at the end of the tline buffer to accommodate this.
+ */
+#define EDITSLOP 10
+
+/*
+ * Globals.
+ */
+
+static bool complement; /* -c: do the complement */
+static bool debugging; /* -d: debugging reports */
+static bool iocccok; /* -e: fewer IOCCC errors */
+static bool killconsts; /* -k: eval constant #ifs */
+static bool lnblank; /* -l: blank deleted lines */
+static bool lnnum; /* -n: add #line directives */
+static bool symlist; /* -s: output symbol list */
+static bool text; /* -t: this is a text file */
+
+static const char *symname[MAXSYMS]; /* symbol name */
+static const char *value[MAXSYMS]; /* -Dsym=value */
+static bool ignore[MAXSYMS]; /* -iDsym or -iUsym */
+static int nsyms; /* number of symbols */
+
+static FILE *input; /* input file pointer */
+static const char *filename; /* input file name */
+static int linenum; /* current line number */
+
+static char tline[MAXLINE+EDITSLOP];/* input buffer plus space */
+static char *keyword; /* used for editing #elif's */
+
+static Comment_state incomment; /* comment parser state */
+static Line_state linestate; /* #if line parser state */
+static Ifstate ifstate[MAXDEPTH]; /* #if processor state */
+static bool ignoring[MAXDEPTH]; /* ignore comments state */
+static int stifline[MAXDEPTH]; /* start of current #if */
+static int depth; /* current #if nesting */
+static int delcount; /* count of deleted lines */
+static bool keepthis; /* don't delete constant #if */
+
+static int exitstat; /* program exit status */
+
+static void addsym(bool, bool, char *);
+static void debug(const char *, ...);
+static void done(void);
+static void error(const char *);
+static int findsym(const char *);
+static void flushline(bool);
+static Linetype getline(void);
+static Linetype ifeval(const char **);
+static void ignoreoff(void);
+static void ignoreon(void);
+static void keywordedit(const char *);
+static void nest(void);
+static void process(void);
+static const char *skipcomment(const char *);
+static const char *skipsym(const char *);
+static void state(Ifstate);
+static int strlcmp(const char *, const char *, size_t);
+static void unnest(void);
+static void usage(void);
+
+#define endsym(c) (!isalpha((unsigned char)c) && !isdigit((unsigned char)c) && c != '_')
+
+/*
+ * The main program.
+ */
+int
+main(int argc, char *argv[])
+{
+ int opt;
+
+ while ((opt = getopt(argc, argv, "i:D:U:I:cdeklnst")) != -1)
+ switch (opt) {
+ case 'i': /* treat stuff controlled by these symbols as text */
+ /*
+ * For strict backwards-compatibility the U or D
+ * should be immediately after the -i but it doesn't
+ * matter much if we relax that requirement.
+ */
+ opt = *optarg++;
+ if (opt == 'D')
+ addsym(true, true, optarg);
+ else if (opt == 'U')
+ addsym(true, false, optarg);
+ else
+ usage();
+ break;
+ case 'D': /* define a symbol */
+ addsym(false, true, optarg);
+ break;
+ case 'U': /* undef a symbol */
+ addsym(false, false, optarg);
+ break;
+ case 'I':
+ /* no-op for compatibility with cpp */
+ break;
+ case 'c': /* treat -D as -U and vice versa */
+ complement = true;
+ break;
+ case 'd':
+ debugging = true;
+ break;
+ case 'e': /* fewer errors from dodgy lines */
+ iocccok = true;
+ break;
+ case 'k': /* process constant #ifs */
+ killconsts = true;
+ break;
+ case 'l': /* blank deleted lines instead of omitting them */
+ lnblank = true;
+ break;
+ case 'n': /* add #line directive after deleted lines */
+ lnnum = true;
+ break;
+ case 's': /* only output list of symbols that control #ifs */
+ symlist = true;
+ break;
+ case 't': /* don't parse C comments */
+ text = true;
+ break;
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+ if (argc > 1) {
+ errx(2, "can only do one file");
+ } else if (argc == 1 && strcmp(*argv, "-") != 0) {
+ filename = *argv;
+ input = fopen(filename, "r");
+ if (input == NULL)
+ err(2, "can't open %s", filename);
+ } else {
+ filename = "[stdin]";
+ input = stdin;
+ }
+ process();
+ abort(); /* bug */
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: unifdef [-cdeklnst] [-Ipath]"
+ " [-Dsym[=val]] [-Usym] [-iDsym[=val]] [-iUsym] ... [file]\n");
+ exit(2);
+}
+
+/*
+ * A state transition function alters the global #if processing state
+ * in a particular way. The table below is indexed by the current
+ * processing state and the type of the current line.
+ *
+ * Nesting is handled by keeping a stack of states; some transition
+ * functions increase or decrease the depth. They also maintain the
+ * ignore state on a stack. In some complicated cases they have to
+ * alter the preprocessor directive, as follows.
+ *
+ * When we have processed a group that starts off with a known-false
+ * #if/#elif sequence (which has therefore been deleted) followed by a
+ * #elif that we don't understand and therefore must keep, we edit the
+ * latter into a #if to keep the nesting correct.
+ *
+ * When we find a true #elif in a group, the following block will
+ * always be kept and the rest of the sequence after the next #elif or
+ * #else will be discarded. We edit the #elif into a #else and the
+ * following directive to #endif since this has the desired behaviour.
+ *
+ * "Dodgy" directives are split across multiple lines, the most common
+ * example being a multi-line comment hanging off the right of the
+ * directive. We can handle them correctly only if there is no change
+ * from printing to dropping (or vice versa) caused by that directive.
+ * If the directive is the first of a group we have a choice between
+ * failing with an error, or passing it through unchanged instead of
+ * evaluating it. The latter is not the default to avoid questions from
+ * users about unifdef unexpectedly leaving behind preprocessor directives.
+ */
+typedef void state_fn(void);
+
+/* report an error */
+static void Eelif (void) { error("Inappropriate #elif"); }
+static void Eelse (void) { error("Inappropriate #else"); }
+static void Eendif(void) { error("Inappropriate #endif"); }
+static void Eeof (void) { error("Premature EOF"); }
+static void Eioccc(void) { error("Obfuscated preprocessor control line"); }
+/* plain line handling */
+static void print (void) { flushline(true); }
+static void drop (void) { flushline(false); }
+/* output lacks group's start line */
+static void Strue (void) { drop(); ignoreoff(); state(IS_TRUE_PREFIX); }
+static void Sfalse(void) { drop(); ignoreoff(); state(IS_FALSE_PREFIX); }
+static void Selse (void) { drop(); state(IS_TRUE_ELSE); }
+/* print/pass this block */
+static void Pelif (void) { print(); ignoreoff(); state(IS_PASS_MIDDLE); }
+static void Pelse (void) { print(); state(IS_PASS_ELSE); }
+static void Pendif(void) { print(); unnest(); }
+/* discard this block */
+static void Dfalse(void) { drop(); ignoreoff(); state(IS_FALSE_TRAILER); }
+static void Delif (void) { drop(); ignoreoff(); state(IS_FALSE_MIDDLE); }
+static void Delse (void) { drop(); state(IS_FALSE_ELSE); }
+static void Dendif(void) { drop(); unnest(); }
+/* first line of group */
+static void Fdrop (void) { nest(); Dfalse(); }
+static void Fpass (void) { nest(); Pelif(); }
+static void Ftrue (void) { nest(); Strue(); }
+static void Ffalse(void) { nest(); Sfalse(); }
+/* variable pedantry for obfuscated lines */
+static void Oiffy (void) { if (!iocccok) Eioccc(); Fpass(); ignoreon(); }
+static void Oif (void) { if (!iocccok) Eioccc(); Fpass(); }
+static void Oelif (void) { if (!iocccok) Eioccc(); Pelif(); }
+/* ignore comments in this block */
+static void Idrop (void) { Fdrop(); ignoreon(); }
+static void Itrue (void) { Ftrue(); ignoreon(); }
+static void Ifalse(void) { Ffalse(); ignoreon(); }
+/* edit this line */
+static void Mpass (void) { strncpy(keyword, "if ", 4); Pelif(); }
+static void Mtrue (void) { keywordedit("else\n"); state(IS_TRUE_MIDDLE); }
+static void Melif (void) { keywordedit("endif\n"); state(IS_FALSE_TRAILER); }
+static void Melse (void) { keywordedit("endif\n"); state(IS_FALSE_ELSE); }
+
+static state_fn * const trans_table[IS_COUNT][LT_COUNT] = {
+/* IS_OUTSIDE */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Eendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eendif,
+ print, done },
+/* IS_FALSE_PREFIX */
+{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Strue, Sfalse,Selse, Dendif,
+ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Mpass, Eioccc,Eioccc,Eioccc,Eioccc,
+ drop, Eeof },
+/* IS_TRUE_PREFIX */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Dfalse,Dfalse,Dfalse,Delse, Dendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
+ print, Eeof },
+/* IS_PASS_MIDDLE */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Pelif, Mtrue, Delif, Pelse, Pendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Pelif, Oelif, Oelif, Pelse, Pendif,
+ print, Eeof },
+/* IS_FALSE_MIDDLE */
+{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Pelif, Mtrue, Delif, Pelse, Pendif,
+ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eioccc,Eioccc,Eioccc,Eioccc,Eioccc,
+ drop, Eeof },
+/* IS_TRUE_MIDDLE */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Melif, Melif, Melif, Melse, Pendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Eioccc,Eioccc,Eioccc,Eioccc,Pendif,
+ print, Eeof },
+/* IS_PASS_ELSE */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Pendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Pendif,
+ print, Eeof },
+/* IS_FALSE_ELSE */
+{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Dendif,
+ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Eelif, Eelif, Eelif, Eelse, Eioccc,
+ drop, Eeof },
+/* IS_TRUE_ELSE */
+{ Itrue, Ifalse,Fpass, Ftrue, Ffalse,Eelif, Eelif, Eelif, Eelse, Dendif,
+ Oiffy, Oiffy, Fpass, Oif, Oif, Eelif, Eelif, Eelif, Eelse, Eioccc,
+ print, Eeof },
+/* IS_FALSE_TRAILER */
+{ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Dendif,
+ Idrop, Idrop, Fdrop, Fdrop, Fdrop, Dfalse,Dfalse,Dfalse,Delse, Eioccc,
+ drop, Eeof }
+/*TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF
+ TRUEI FALSEI IF TRUE FALSE ELIF ELTRUE ELFALSE ELSE ENDIF (DODGY)
+ PLAIN EOF */
+};
+
+/*
+ * State machine utility functions
+ */
+static void
+done(void)
+{
+ if (incomment)
+ error("EOF in comment");
+ exit(exitstat);
+}
+static void
+ignoreoff(void)
+{
+ if (depth == 0)
+ abort(); /* bug */
+ ignoring[depth] = ignoring[depth-1];
+}
+static void
+ignoreon(void)
+{
+ ignoring[depth] = true;
+}
+static void
+keywordedit(const char *replacement)
+{
+ size_t size = tline + sizeof(tline) - keyword;
+ char *dst = keyword;
+ const char *src = replacement;
+ if (size != 0) {
+ while ((--size != 0) && (*src != '\0'))
+ *dst++ = *src++;
+ *dst = '\0';
+ }
+ print();
+}
+static void
+nest(void)
+{
+ depth += 1;
+ if (depth >= MAXDEPTH)
+ error("Too many levels of nesting");
+ stifline[depth] = linenum;
+}
+static void
+unnest(void)
+{
+ if (depth == 0)
+ abort(); /* bug */
+ depth -= 1;
+}
+static void
+state(Ifstate is)
+{
+ ifstate[depth] = is;
+}
+
+/*
+ * Write a line to the output or not, according to command line options.
+ */
+static void
+flushline(bool keep)
+{
+ if (symlist)
+ return;
+ if (keep ^ complement) {
+ if (lnnum && delcount > 0)
+ printf("#line %d\n", linenum);
+ fputs(tline, stdout);
+ delcount = 0;
+ } else {
+ if (lnblank)
+ putc('\n', stdout);
+ exitstat = 1;
+ delcount += 1;
+ }
+}
+
+/*
+ * The driver for the state machine.
+ */
+static void
+process(void)
+{
+ Linetype lineval;
+
+ for (;;) {
+ linenum++;
+ lineval = getline();
+ trans_table[ifstate[depth]][lineval]();
+ debug("process %s -> %s depth %d",
+ linetype_name[lineval],
+ ifstate_name[ifstate[depth]], depth);
+ }
+}
+
+/*
+ * Parse a line and determine its type. We keep the preprocessor line
+ * parser state between calls in the global variable linestate, with
+ * help from skipcomment().
+ */
+static Linetype
+getline(void)
+{
+ const char *cp;
+ int cursym;
+ int kwlen;
+ Linetype retval;
+ Comment_state wascomment;
+
+ if (fgets(tline, MAXLINE, input) == NULL)
+ return (LT_EOF);
+ retval = LT_PLAIN;
+ wascomment = incomment;
+ cp = skipcomment(tline);
+ if (linestate == LS_START) {
+ if (*cp == '#') {
+ linestate = LS_HASH;
+ cp = skipcomment(cp + 1);
+ } else if (*cp != '\0')
+ linestate = LS_DIRTY;
+ }
+ if (!incomment && linestate == LS_HASH) {
+ keyword = tline + (cp - tline);
+ cp = skipsym(cp);
+ kwlen = cp - keyword;
+ /* no way can we deal with a continuation inside a keyword */
+ if (strncmp(cp, "\\\n", 2) == 0)
+ Eioccc();
+ if (strlcmp("ifdef", keyword, kwlen) == 0 ||
+ strlcmp("ifndef", keyword, kwlen) == 0) {
+ cp = skipcomment(cp);
+ if ((cursym = findsym(cp)) < 0)
+ retval = LT_IF;
+ else {
+ retval = (keyword[2] == 'n')
+ ? LT_FALSE : LT_TRUE;
+ if (value[cursym] == NULL)
+ retval = (retval == LT_TRUE)
+ ? LT_FALSE : LT_TRUE;
+ if (ignore[cursym])
+ retval = (retval == LT_TRUE)
+ ? LT_TRUEI : LT_FALSEI;
+ }
+ cp = skipsym(cp);
+ } else if (strlcmp("if", keyword, kwlen) == 0)
+ retval = ifeval(&cp);
+ else if (strlcmp("elif", keyword, kwlen) == 0)
+ retval = ifeval(&cp) - LT_IF + LT_ELIF;
+ else if (strlcmp("else", keyword, kwlen) == 0)
+ retval = LT_ELSE;
+ else if (strlcmp("endif", keyword, kwlen) == 0)
+ retval = LT_ENDIF;
+ else {
+ linestate = LS_DIRTY;
+ retval = LT_PLAIN;
+ }
+ cp = skipcomment(cp);
+ if (*cp != '\0') {
+ linestate = LS_DIRTY;
+ if (retval == LT_TRUE || retval == LT_FALSE ||
+ retval == LT_TRUEI || retval == LT_FALSEI)
+ retval = LT_IF;
+ if (retval == LT_ELTRUE || retval == LT_ELFALSE)
+ retval = LT_ELIF;
+ }
+ if (retval != LT_PLAIN && (wascomment || incomment)) {
+ retval += LT_DODGY;
+ if (incomment)
+ linestate = LS_DIRTY;
+ }
+ /* skipcomment should have changed the state */
+ if (linestate == LS_HASH)
+ abort(); /* bug */
+ }
+ if (linestate == LS_DIRTY) {
+ while (*cp != '\0')
+ cp = skipcomment(cp + 1);
+ }
+ debug("parser %s comment %s line",
+ comment_name[incomment], linestate_name[linestate]);
+ return (retval);
+}
+
+/*
+ * These are the binary operators that are supported by the expression
+ * evaluator. Note that if support for division is added then we also
+ * need short-circuiting booleans because of divide-by-zero.
+ */
+static int op_lt(int a, int b) { return (a < b); }
+static int op_gt(int a, int b) { return (a > b); }
+static int op_le(int a, int b) { return (a <= b); }
+static int op_ge(int a, int b) { return (a >= b); }
+static int op_eq(int a, int b) { return (a == b); }
+static int op_ne(int a, int b) { return (a != b); }
+static int op_or(int a, int b) { return (a || b); }
+static int op_and(int a, int b) { return (a && b); }
+
+/*
+ * An evaluation function takes three arguments, as follows: (1) a pointer to
+ * an element of the precedence table which lists the operators at the current
+ * level of precedence; (2) a pointer to an integer which will receive the
+ * value of the expression; and (3) a pointer to a char* that points to the
+ * expression to be evaluated and that is updated to the end of the expression
+ * when evaluation is complete. The function returns LT_FALSE if the value of
+ * the expression is zero, LT_TRUE if it is non-zero, or LT_IF if the
+ * expression could not be evaluated.
+ */
+struct ops;
+
+typedef Linetype eval_fn(const struct ops *, int *, const char **);
+
+static eval_fn eval_table, eval_unary;
+
+/*
+ * The precedence table. Expressions involving binary operators are evaluated
+ * in a table-driven way by eval_table. When it evaluates a subexpression it
+ * calls the inner function with its first argument pointing to the next
+ * element of the table. Innermost expressions have special non-table-driven
+ * handling.
+ */
+static const struct ops {
+ eval_fn *inner;
+ struct op {
+ const char *str;
+ int (*fn)(int, int);
+ } op[5];
+} eval_ops[] = {
+ { eval_table, { { "||", op_or } } },
+ { eval_table, { { "&&", op_and } } },
+ { eval_table, { { "==", op_eq },
+ { "!=", op_ne } } },
+ { eval_unary, { { "<=", op_le },
+ { ">=", op_ge },
+ { "<", op_lt },
+ { ">", op_gt } } }
+};
+
+/*
+ * Function for evaluating the innermost parts of expressions,
+ * viz. !expr (expr) defined(symbol) symbol number
+ * We reset the keepthis flag when we find a non-constant subexpression.
+ */
+static Linetype
+eval_unary(const struct ops *ops, int *valp, const char **cpp)
+{
+ const char *cp;
+ char *ep;
+ int sym;
+
+ cp = skipcomment(*cpp);
+ if (*cp == '!') {
+ debug("eval%d !", ops - eval_ops);
+ cp++;
+ if (eval_unary(ops, valp, &cp) == LT_IF)
+ return (LT_IF);
+ *valp = !*valp;
+ } else if (*cp == '(') {
+ cp++;
+ debug("eval%d (", ops - eval_ops);
+ if (eval_table(eval_ops, valp, &cp) == LT_IF)
+ return (LT_IF);
+ cp = skipcomment(cp);
+ if (*cp++ != ')')
+ return (LT_IF);
+ } else if (isdigit((unsigned char)*cp)) {
+ debug("eval%d number", ops - eval_ops);
+ *valp = strtol(cp, &ep, 0);
+ cp = skipsym(cp);
+ } else if (strncmp(cp, "defined", 7) == 0 && endsym(cp[7])) {
+ cp = skipcomment(cp+7);
+ debug("eval%d defined", ops - eval_ops);
+ if (*cp++ != '(')
+ return (LT_IF);
+ cp = skipcomment(cp);
+ sym = findsym(cp);
+ if (sym < 0)
+ return (LT_IF);
+ *valp = (value[sym] != NULL);
+ cp = skipsym(cp);
+ cp = skipcomment(cp);
+ if (*cp++ != ')')
+ return (LT_IF);
+ keepthis = false;
+ } else if (!endsym(*cp)) {
+ debug("eval%d symbol", ops - eval_ops);
+ sym = findsym(cp);
+ if (sym < 0)
+ return (LT_IF);
+ if (value[sym] == NULL)
+ *valp = 0;
+ else {
+ *valp = strtol(value[sym], &ep, 0);
+ if (*ep != '\0' || ep == value[sym])
+ return (LT_IF);
+ }
+ cp = skipsym(cp);
+ keepthis = false;
+ } else {
+ debug("eval%d bad expr", ops - eval_ops);
+ return (LT_IF);
+ }
+
+ *cpp = cp;
+ debug("eval%d = %d", ops - eval_ops, *valp);
+ return (*valp ? LT_TRUE : LT_FALSE);
+}
+
+/*
+ * Table-driven evaluation of binary operators.
+ */
+static Linetype
+eval_table(const struct ops *ops, int *valp, const char **cpp)
+{
+ const struct op *op;
+ const char *cp;
+ int val;
+
+ debug("eval%d", ops - eval_ops);
+ cp = *cpp;
+ if (ops->inner(ops+1, valp, &cp) == LT_IF)
+ return (LT_IF);
+ for (;;) {
+ cp = skipcomment(cp);
+ for (op = ops->op; op->str != NULL; op++)
+ if (strncmp(cp, op->str, strlen(op->str)) == 0)
+ break;
+ if (op->str == NULL)
+ break;
+ cp += strlen(op->str);
+ debug("eval%d %s", ops - eval_ops, op->str);
+ if (ops->inner(ops+1, &val, &cp) == LT_IF)
+ return (LT_IF);
+ *valp = op->fn(*valp, val);
+ }
+
+ *cpp = cp;
+ debug("eval%d = %d", ops - eval_ops, *valp);
+ return (*valp ? LT_TRUE : LT_FALSE);
+}
+
+/*
+ * Evaluate the expression on a #if or #elif line. If we can work out
+ * the result we return LT_TRUE or LT_FALSE accordingly, otherwise we
+ * return just a generic LT_IF.
+ */
+static Linetype
+ifeval(const char **cpp)
+{
+ int ret;
+ int val;
+
+ debug("eval %s", *cpp);
+ keepthis = killconsts ? false : true;
+ ret = eval_table(eval_ops, &val, cpp);
+ debug("eval = %d", val);
+ return (keepthis ? LT_IF : ret);
+}
+
+/*
+ * Skip over comments, strings, and character literals and stop at the
+ * next character position that is not whitespace. Between calls we keep
+ * the comment state in the global variable incomment, and we also adjust
+ * the global variable linestate when we see a newline.
+ * XXX: doesn't cope with the buffer splitting inside a state transition.
+ */
+static const char *
+skipcomment(const char *cp)
+{
+ if (text || ignoring[depth]) {
+ for (; isspace((unsigned char)*cp); cp++)
+ if (*cp == '\n')
+ linestate = LS_START;
+ return (cp);
+ }
+ while (*cp != '\0')
+ /* don't reset to LS_START after a line continuation */
+ if (strncmp(cp, "\\\n", 2) == 0)
+ cp += 2;
+ else switch (incomment) {
+ case NO_COMMENT:
+ if (strncmp(cp, "/\\\n", 3) == 0) {
+ incomment = STARTING_COMMENT;
+ cp += 3;
+ } else if (strncmp(cp, "/*", 2) == 0) {
+ incomment = C_COMMENT;
+ cp += 2;
+ } else if (strncmp(cp, "//", 2) == 0) {
+ incomment = CXX_COMMENT;
+ cp += 2;
+ } else if (strncmp(cp, "\'", 1) == 0) {
+ incomment = CHAR_LITERAL;
+ linestate = LS_DIRTY;
+ cp += 1;
+ } else if (strncmp(cp, "\"", 1) == 0) {
+ incomment = STRING_LITERAL;
+ linestate = LS_DIRTY;
+ cp += 1;
+ } else if (strncmp(cp, "\n", 1) == 0) {
+ linestate = LS_START;
+ cp += 1;
+ } else if (strchr(" \t", *cp) != NULL) {
+ cp += 1;
+ } else
+ return (cp);
+ continue;
+ case CXX_COMMENT:
+ if (strncmp(cp, "\n", 1) == 0) {
+ incomment = NO_COMMENT;
+ linestate = LS_START;
+ }
+ cp += 1;
+ continue;
+ case CHAR_LITERAL:
+ case STRING_LITERAL:
+ if ((incomment == CHAR_LITERAL && cp[0] == '\'') ||
+ (incomment == STRING_LITERAL && cp[0] == '\"')) {
+ incomment = NO_COMMENT;
+ cp += 1;
+ } else if (cp[0] == '\\') {
+ if (cp[1] == '\0')
+ cp += 1;
+ else
+ cp += 2;
+ } else if (strncmp(cp, "\n", 1) == 0) {
+ if (incomment == CHAR_LITERAL)
+ error("unterminated char literal");
+ else
+ error("unterminated string literal");
+ } else
+ cp += 1;
+ continue;
+ case C_COMMENT:
+ if (strncmp(cp, "*\\\n", 3) == 0) {
+ incomment = FINISHING_COMMENT;
+ cp += 3;
+ } else if (strncmp(cp, "*/", 2) == 0) {
+ incomment = NO_COMMENT;
+ cp += 2;
+ } else
+ cp += 1;
+ continue;
+ case STARTING_COMMENT:
+ if (*cp == '*') {
+ incomment = C_COMMENT;
+ cp += 1;
+ } else if (*cp == '/') {
+ incomment = CXX_COMMENT;
+ cp += 1;
+ } else {
+ incomment = NO_COMMENT;
+ linestate = LS_DIRTY;
+ }
+ continue;
+ case FINISHING_COMMENT:
+ if (*cp == '/') {
+ incomment = NO_COMMENT;
+ cp += 1;
+ } else
+ incomment = C_COMMENT;
+ continue;
+ default:
+ abort(); /* bug */
+ }
+ return (cp);
+}
+
+/*
+ * Skip over an identifier.
+ */
+static const char *
+skipsym(const char *cp)
+{
+ while (!endsym(*cp))
+ ++cp;
+ return (cp);
+}
+
+/*
+ * Look for the symbol in the symbol table. If is is found, we return
+ * the symbol table index, else we return -1.
+ */
+static int
+findsym(const char *str)
+{
+ const char *cp;
+ int symind;
+
+ cp = skipsym(str);
+ if (cp == str)
+ return (-1);
+ if (symlist) {
+ printf("%.*s\n", (int)(cp-str), str);
+ /* we don't care about the value of the symbol */
+ return (0);
+ }
+ for (symind = 0; symind < nsyms; ++symind) {
+ if (strlcmp(symname[symind], str, cp-str) == 0) {
+ debug("findsym %s %s", symname[symind],
+ value[symind] ? value[symind] : "");
+ return (symind);
+ }
+ }
+ return (-1);
+}
+
+/*
+ * Add a symbol to the symbol table.
+ */
+static void
+addsym(bool ignorethis, bool definethis, char *sym)
+{
+ int symind;
+ char *val;
+
+ symind = findsym(sym);
+ if (symind < 0) {
+ if (nsyms >= MAXSYMS)
+ errx(2, "too many symbols");
+ symind = nsyms++;
+ }
+ symname[symind] = sym;
+ ignore[symind] = ignorethis;
+ val = sym + (skipsym(sym) - sym);
+ if (definethis) {
+ if (*val == '=') {
+ value[symind] = val+1;
+ *val = '\0';
+ } else if (*val == '\0')
+ value[symind] = "";
+ else
+ usage();
+ } else {
+ if (*val != '\0')
+ usage();
+ value[symind] = NULL;
+ }
+}
+
+/*
+ * Compare s with n characters of t.
+ * The same as strncmp() except that it checks that s[n] == '\0'.
+ */
+static int
+strlcmp(const char *s, const char *t, size_t n)
+{
+ while (n-- && *t != '\0')
+ if (*s != *t)
+ return ((unsigned char)*s - (unsigned char)*t);
+ else
+ ++s, ++t;
+ return ((unsigned char)*s);
+}
+
+/*
+ * Diagnostics.
+ */
+static void
+debug(const char *msg, ...)
+{
+ va_list ap;
+
+ if (debugging) {
+ va_start(ap, msg);
+ vwarnx(msg, ap);
+ va_end(ap);
+ }
+}
+
+static void
+error(const char *msg)
+{
+ if (depth == 0)
+ warnx("%s: %d: %s", filename, linenum, msg);
+ else
+ warnx("%s: %d: %s (#if line %d depth %d)",
+ filename, linenum, msg, stifline[depth], depth);
+ errx(2, "output may be truncated");
+}
diff --git a/include/libc-symbols.h b/include/libc-symbols.h
index 6e9c5c9f0..e491aff5f 100644
--- a/include/libc-symbols.h
+++ b/include/libc-symbols.h
@@ -22,6 +22,16 @@
#ifndef _LIBC_SYMBOLS_H
#define _LIBC_SYMBOLS_H 1
+/* This is defined for the compilation of all C library code. features.h
+ tests this to avoid inclusion of stubs.h while compiling the library,
+ before stubs.h has been generated. Some library code that is shared
+ with other packages also tests this symbol to see if it is being
+ compiled as part of the C library. We must define this before including
+ config.h, because it makes some definitions conditional on whether libc
+ itself is being compiled, or just some generator program. */
+#define _LIBC 1
+
+
/* This file's macros are included implicitly in the compilation of every
file in the C library by -imacros.
@@ -40,21 +50,11 @@
#include <bits/uClibc_arch_features.h>
-
-/* This is defined for the compilation of all C library code. features.h
- tests this to avoid inclusion of stubs.h while compiling the library,
- before stubs.h has been generated. Some library code that is shared
- with other packages also tests this symbol to see if it is being
- compiled as part of the C library. We must define this before including
- config.h, because it makes some definitions conditional on whether libc
- itself is being compiled, or just some generator program. */
-#define _LIBC 1
-
/* Enable declarations of GNU extensions, since we are compiling them. */
#define _GNU_SOURCE 1
/* Prepare for the case that `__builtin_expect' is not available. */
-#if __GNUC__ == 2 && __GNUC_MINOR__ < 96
+#if defined __GNUC__ && __GNUC__ == 2 && __GNUC_MINOR__ < 96
# define __builtin_expect(x, expected_value) (x)
#endif
#ifndef likely
@@ -72,7 +72,7 @@
#define attribute_unused __attribute__ ((unused))
-#ifdef __GNUC__
+#if defined __GNUC__ || defined __ICC
# define attribute_noreturn __attribute__ ((__noreturn__))
#else
# define attribute_noreturn
@@ -82,12 +82,6 @@
# define IS_IN_libc 1
#endif
-#ifdef __UCLIBC_NO_UNDERSCORES__
-# define NO_UNDERSCORES
-#else
-# undef NO_UNDERSCORES
-#endif
-
#ifdef __UCLIBC_HAVE_ASM_SET_DIRECTIVE__
# define HAVE_ASM_SET_DIRECTIVE
#else
@@ -124,14 +118,16 @@
#undef C_SYMBOL_NAME
#ifndef C_SYMBOL_NAME
-# ifdef NO_UNDERSCORES
+# ifndef __UCLIBC_UNDERSCORES__
# define C_SYMBOL_NAME(name) name
# else
# define C_SYMBOL_NAME(name) _##name
# endif
#endif
-#ifndef ASM_LINE_SEP
+#ifdef __UCLIBC_ASM_LINE_SEP__
+# define ASM_LINE_SEP __UCLIBC_ASM_LINE_SEP__
+#else
# define ASM_LINE_SEP ;
#endif
@@ -174,9 +170,6 @@
# else
-# define weak_function /* empty */
-# define weak_const_function /* empty */
-
# define weak_alias(name, aliasname) strong_alias(name, aliasname)
# define weak_extern(symbol) /* Nothing. */
@@ -246,17 +239,17 @@
.set C_SYMBOL_NAME (alias), C_SYMBOL_NAME (original)
# endif
# else /* ! HAVE_ASM_SET_DIRECTIVE */
-# ifdef HAVE_ASM_GLOBAL_DOT_NAME
-# define weak_alias(original, alias) \
+# ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define weak_alias(original, alias) \
.weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \
C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original) ASM_LINE_SEP \
.weak C_SYMBOL_DOT_NAME (alias) ASM_LINE_SEP \
C_SYMBOL_DOT_NAME (alias) = C_SYMBOL_DOT_NAME (original)
-# else
-# define weak_alias(original, alias) \
+# else
+# define weak_alias(original, alias) \
.weak C_SYMBOL_NAME (alias) ASM_LINE_SEP \
C_SYMBOL_NAME (alias) = C_SYMBOL_NAME (original)
-# endif
+# endif
# endif
# define weak_extern(symbol) \
.weak C_SYMBOL_NAME (symbol)
@@ -282,25 +275,21 @@
#define __make_section_unallocated(section_string) \
__asm__ (".section " section_string "\n\t.previous");
-/* Tacking on "\n\t#" to the section name makes gcc put it's bogus
+/* Tacking on "\n#APP\n\t#" to the section name makes gcc put it's bogus
section attributes on what looks like a comment to the assembler. */
#ifdef __sparc__ //HAVE_SECTION_QUOTES
-# define __sec_comment "\"\n\t#\""
+# define __sec_comment "\"\n#APP\n\t#\""
#else
-# define __sec_comment "\n\t#"
+# define __sec_comment "\n#APP\n\t#"
#endif
/* When a reference to SYMBOL is encountered, the linker will emit a
warning message MSG. */
-#if defined(__cris__) || defined(__vax__)
-# define link_warning(symbol, msg)
-#else
-# define link_warning(symbol, msg) \
+#define link_warning(symbol, msg) \
__make_section_unallocated (".gnu.warning." #symbol) \
static const char __evoke_link_warning_##symbol[] \
__attribute__ ((used, section (".gnu.warning." #symbol __sec_comment))) \
= msg;
-#endif
/* Handling on non-exported internal names. We have to do this only
for shared code. */
@@ -414,8 +403,9 @@
* d. hidden_def() in asm is _hidden_strong_alias (not strong_alias) */
/* Arrange to hide uClibc internals */
-#if defined __GNUC__ && defined __GNUC_MINOR__ && \
- ( __GNUC__ >= 3 && __GNUC_MINOR__ >= 3 ) || __GNUC__ >= 4
+#if (defined __GNUC__ && \
+ (defined __GNUC_MINOR__ && ( __GNUC__ >= 3 && __GNUC_MINOR__ >= 3 ) \
+ || __GNUC__ >= 4)) || defined __ICC
# define attribute_hidden __attribute__ ((visibility ("hidden")))
# define __hidden_proto_hiddenattr(attrs...) __attribute__ ((visibility ("hidden"), ##attrs))
#else
@@ -423,7 +413,7 @@
# define __hidden_proto_hiddenattr(attrs...)
#endif
-#if !defined STATIC && !defined __BCC__
+#if /*!defined STATIC &&*/ !defined __BCC__
# ifndef __ASSEMBLER__
# define hidden_proto(name, attrs...) __hidden_proto (name, __GI_##name, ##attrs)
# define __hidden_proto(name, internal, attrs...) \
@@ -435,9 +425,12 @@
# define __hidden_ver1(local, internal, name) \
extern __typeof (name) __EI_##name __asm__(__hidden_asmname (#internal)); \
extern __typeof (name) __EI_##name __attribute__((alias (__hidden_asmname1 (,#local))))
+# define hidden_ver(local, name) __hidden_ver1(local, __GI_##name, name);
+# define hidden_data_ver(local, name) hidden_ver(local, name)
# define hidden_def(name) __hidden_ver1(__GI_##name, name, name);
# define hidden_data_def(name) hidden_def(name)
-# define hidden_weak(name) __hidden_ver1(__GI_##name, name, name) __attribute__((weak));
+# define hidden_weak(name) \
+ __hidden_ver1(__GI_##name, name, name) __attribute__((weak));
# define hidden_data_weak(name) hidden_weak(name)
# else /* __ASSEMBLER__ */
@@ -494,26 +487,36 @@
hidden_proto doesn't make sense for assembly but the equivalent
is to call via the HIDDEN_JUMPTARGET macro instead of JUMPTARGET. */
# define hidden_def(name) _hidden_strong_alias (name, __GI_##name)
-# define hidden_data_def(name) _hidden_strong_alias (name, __GI_##name)
# define hidden_weak(name) _hidden_weak_alias (name, __GI_##name)
+# define hidden_ver(local, name) strong_alias (local, __GI_##name)
+# define hidden_data_def(name) _hidden_strong_alias (name, __GI_##name)
# define hidden_data_weak(name) _hidden_weak_alias (name, __GI_##name)
-# define HIDDEN_JUMPTARGET(name) __GI_##name
+# define hidden_data_ver(local, name) strong_data_alias (local, __GI_##name)
+# ifdef HAVE_ASM_GLOBAL_DOT_NAME
+# define HIDDEN_JUMPTARGET(name) .__GI_##name
+# else
+# define HIDDEN_JUMPTARGET(name) __GI_##name
+# endif
# endif /* __ASSEMBLER__ */
#else /* SHARED */
# ifndef __ASSEMBLER__
# define hidden_proto(name, attrs...)
# else
# define HIDDEN_JUMPTARGET(name) name
-# endif
-# define hidden_def(name)
-# define hidden_data_def(name)
+# endif /* Not __ASSEMBLER__ */
# define hidden_weak(name)
+# define hidden_def(name)
+# define hidden_ver(local, name)
# define hidden_data_weak(name)
+# define hidden_data_def(name)
+# define hidden_data_ver(local, name)
#endif /* SHARED */
/* uClibc does not support versioning yet. */
#define versioned_symbol(lib, local, symbol, version) /* weak_alias(local, symbol) */
+#undef hidden_ver
#define hidden_ver(local, name) /* strong_alias(local, __GI_##name) */
+#undef hidden_data_ver
#define hidden_data_ver(local, name) /* strong_alias(local,__GI_##name) */
#if !defined NOT_IN_libc
diff --git a/include/string.h b/include/string.h
index 87d953449..35807d6a7 100644
--- a/include/string.h
+++ b/include/string.h
@@ -38,10 +38,12 @@ __BEGIN_NAMESPACE_STD
extern void *memcpy (void *__restrict __dest,
__const void *__restrict __src, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(memcpy)
/* Copy N bytes of SRC to DEST, guaranteeing
correct behavior for overlapping strings. */
extern void *memmove (void *__dest, __const void *__src, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(memmove)
__END_NAMESPACE_STD
/* Copy no more than N bytes of SRC to DEST, stopping when C is found.
@@ -51,20 +53,24 @@ __END_NAMESPACE_STD
extern void *memccpy (void *__restrict __dest, __const void *__restrict __src,
int __c, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(memccpy)
#endif /* SVID. */
__BEGIN_NAMESPACE_STD
/* Set N bytes of S to C. */
extern void *memset (void *__s, int __c, size_t __n) __THROW __nonnull ((1));
+libc_hidden_proto(memset)
/* Compare N bytes of S1 and S2. */
extern int memcmp (__const void *__s1, __const void *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(memcmp)
/* Search N bytes of S for C. */
extern void *memchr (__const void *__s, int __c, size_t __n)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(memchr)
__END_NAMESPACE_STD
#ifdef __USE_GNU
@@ -72,10 +78,12 @@ __END_NAMESPACE_STD
length limit. */
extern void *rawmemchr (__const void *__s, int __c)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(rawmemchr)
/* Search N bytes of S for the final occurrence of C. */
extern void *memrchr (__const void *__s, int __c, size_t __n)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(memrchr)
#endif
@@ -83,32 +91,40 @@ __BEGIN_NAMESPACE_STD
/* Copy SRC to DEST. */
extern char *strcpy (char *__restrict __dest, __const char *__restrict __src)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(strcpy)
/* Copy no more than N characters of SRC to DEST. */
extern char *strncpy (char *__restrict __dest,
__const char *__restrict __src, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(strncpy)
/* Append SRC onto DEST. */
extern char *strcat (char *__restrict __dest, __const char *__restrict __src)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(strcat)
/* Append no more than N characters from SRC onto DEST. */
extern char *strncat (char *__restrict __dest, __const char *__restrict __src,
size_t __n) __THROW __nonnull ((1, 2));
+libc_hidden_proto(strncat)
/* Compare S1 and S2. */
extern int strcmp (__const char *__s1, __const char *__s2)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strcmp)
/* Compare N characters of S1 and S2. */
extern int strncmp (__const char *__s1, __const char *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strncmp)
/* Compare the collated forms of S1 and S2. */
extern int strcoll (__const char *__s1, __const char *__s2)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strcoll)
/* Put a transformation of SRC into no more than N bytes of DEST. */
extern size_t strxfrm (char *__restrict __dest,
__const char *__restrict __src, size_t __n)
__THROW __nonnull ((2));
+libc_hidden_proto(strxfrm)
__END_NAMESPACE_STD
#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__
@@ -120,15 +136,18 @@ __END_NAMESPACE_STD
/* Compare the collated forms of S1 and S2 using rules from L. */
extern int strcoll_l (__const char *__s1, __const char *__s2, __locale_t __l)
__THROW __attribute_pure__ __nonnull ((1, 2, 3));
+libc_hidden_proto(strcoll_l)
/* Put a transformation of SRC into no more than N bytes of DEST. */
extern size_t strxfrm_l (char *__dest, __const char *__src, size_t __n,
__locale_t __l) __THROW __nonnull ((2, 4));
+libc_hidden_proto(strxfrm_l)
#endif
#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
/* Duplicate S, returning an identical malloc'd string. */
extern char *strdup (__const char *__s)
__THROW __attribute_malloc__ __nonnull ((1));
+libc_hidden_proto(strdup)
#endif
/* Return a malloc'd copy of at most N bytes of STRING. The
@@ -137,6 +156,7 @@ extern char *strdup (__const char *__s)
#if defined __USE_GNU
extern char *strndup (__const char *__string, size_t __n)
__THROW __attribute_malloc__ __nonnull ((1));
+libc_hidden_proto(strndup)
#endif
#if defined __USE_GNU && defined __GNUC__
@@ -166,9 +186,11 @@ __BEGIN_NAMESPACE_STD
/* Find the first occurrence of C in S. */
extern char *strchr (__const char *__s, int __c)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(strchr)
/* Find the last occurrence of C in S. */
extern char *strrchr (__const char *__s, int __c)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(strrchr)
__END_NAMESPACE_STD
#ifdef __USE_GNU
@@ -176,6 +198,7 @@ __END_NAMESPACE_STD
the closing NUL byte in case C is not found in S. */
extern char *strchrnul (__const char *__s, int __c)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(strchrnul)
#endif
__BEGIN_NAMESPACE_STD
@@ -183,21 +206,26 @@ __BEGIN_NAMESPACE_STD
consists entirely of characters not in REJECT. */
extern size_t strcspn (__const char *__s, __const char *__reject)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strcspn)
/* Return the length of the initial segment of S which
consists entirely of characters in ACCEPT. */
extern size_t strspn (__const char *__s, __const char *__accept)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strspn)
/* Find the first occurrence in S of any character in ACCEPT. */
extern char *strpbrk (__const char *__s, __const char *__accept)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strpbrk)
/* Find the first occurrence of NEEDLE in HAYSTACK. */
extern char *strstr (__const char *__haystack, __const char *__needle)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strstr)
/* Divide S into tokens separated by characters in DELIM. */
extern char *strtok (char *__restrict __s, __const char *__restrict __delim)
__THROW __nonnull ((2));
+libc_hidden_proto(strtok)
__END_NAMESPACE_STD
/* Divide S into tokens separated by characters in DELIM. Information
@@ -212,12 +240,14 @@ extern char *__strtok_r (char *__restrict __s,
extern char *strtok_r (char *__restrict __s, __const char *__restrict __delim,
char **__restrict __save_ptr)
__THROW __nonnull ((2, 3));
+libc_hidden_proto(strtok_r)
#endif
#ifdef __USE_GNU
/* Similar to `strstr' but this function ignores the case of both strings. */
extern char *strcasestr (__const char *__haystack, __const char *__needle)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strcasestr)
#endif
#ifdef __USE_GNU
@@ -227,6 +257,7 @@ extern char *strcasestr (__const char *__haystack, __const char *__needle)
extern void *memmem (__const void *__haystack, size_t __haystacklen,
__const void *__needle, size_t __needlelen)
__THROW __attribute_pure__ __nonnull ((1, 3));
+libc_hidden_proto(memmem)
/* Copy N bytes of SRC to DEST, return pointer to bytes after the
last written byte. */
@@ -238,6 +269,7 @@ extern void *__mempcpy (void *__restrict __dest,
extern void *mempcpy (void *__restrict __dest,
__const void *__restrict __src, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(mempcpy)
#endif
@@ -245,6 +277,7 @@ __BEGIN_NAMESPACE_STD
/* Return the length of S. */
extern size_t strlen (__const char *__s)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(strlen)
__END_NAMESPACE_STD
#ifdef __USE_GNU
@@ -252,12 +285,14 @@ __END_NAMESPACE_STD
If no '\0' terminator is found in that many characters, return MAXLEN. */
extern size_t strnlen (__const char *__string, size_t __maxlen)
__THROW __attribute_pure__ __nonnull ((1));
+libc_hidden_proto(strnlen)
#endif
__BEGIN_NAMESPACE_STD
/* Return a string describing the meaning of the `errno' code in ERRNUM. */
extern char *strerror (int __errnum) __THROW;
+libc_hidden_proto(strerror)
__END_NAMESPACE_STD
#if defined __USE_XOPEN2K || defined __USE_MISC
/* Reentrant version of `strerror'.
@@ -337,6 +372,7 @@ extern char *rindex (__const char *__s, int __c)
/* Return the position of the first bit set in I, or 0 if none are set.
The least-significant bit is position 1, the most-significant 32. */
extern int ffs (int __i) __THROW __attribute__ ((__const__));
+libc_hidden_proto(ffs)
/* The following two functions are non-standard but necessary for non-32 bit
platforms. */
@@ -351,10 +387,12 @@ __extension__ extern int ffsll (long long int __ll)
/* Compare S1 and S2, ignoring case. */
extern int strcasecmp (__const char *__s1, __const char *__s2)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strcasecmp)
/* Compare no more than N chars of S1 and S2, ignoring case. */
extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strncasecmp)
#endif /* Use BSD. */
#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__
@@ -363,10 +401,12 @@ extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n)
extern int strcasecmp_l (__const char *__s1, __const char *__s2,
__locale_t __loc)
__THROW __attribute_pure__ __nonnull ((1, 2, 3));
+libc_hidden_proto(strcasecmp_l)
extern int strncasecmp_l (__const char *__s1, __const char *__s2,
size_t __n, __locale_t __loc)
__THROW __attribute_pure__ __nonnull ((1, 2, 4));
+libc_hidden_proto(strncasecmp_l)
#endif
#ifdef __USE_BSD
@@ -375,6 +415,7 @@ extern int strncasecmp_l (__const char *__s1, __const char *__s2,
extern char *strsep (char **__restrict __stringp,
__const char *__restrict __delim)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(strsep)
#endif
#ifdef __USE_GNU
@@ -382,10 +423,12 @@ extern char *strsep (char **__restrict __stringp,
#if 0
extern int strverscmp (__const char *__s1, __const char *__s2)
__THROW __attribute_pure__ __nonnull ((1, 2));
+libc_hidden_proto(strverscmp)
#endif
/* Return a string describing the meaning of the signal number in SIG. */
extern char *strsignal (int __sig) __THROW;
+libc_hidden_proto(strsignal)
/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */
#if 0 /* uClibc: disabled */
@@ -394,6 +437,7 @@ extern char *__stpcpy (char *__restrict __dest, __const char *__restrict __src)
#endif
extern char *stpcpy (char *__restrict __dest, __const char *__restrict __src)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(stpcpy)
/* Copy no more than N characters of SRC to DEST, returning the address of
the last character written into DEST. */
@@ -405,6 +449,7 @@ extern char *__stpncpy (char *__restrict __dest,
extern char *stpncpy (char *__restrict __dest,
__const char *__restrict __src, size_t __n)
__THROW __nonnull ((1, 2));
+libc_hidden_proto(stpncpy)
#if 0 /* uClibc does not support strfry or memfrob. */
/* Sautee STRING briskly. */
@@ -420,6 +465,7 @@ extern void *memfrob (void *__s, size_t __n) __THROW __nonnull ((1));
in <libgen.h>) which makes the XPG version of this function
available. */
extern char *basename (__const char *__filename) __THROW __nonnull ((1));
+libc_hidden_proto(basename)
# endif
#endif
@@ -428,10 +474,127 @@ extern char *basename (__const char *__filename) __THROW __nonnull ((1));
/* Two OpenBSD extension functions. */
extern size_t strlcat(char *__restrict dst, const char *__restrict src,
size_t n) __THROW __nonnull ((1, 2));
+libc_hidden_proto(strlcat)
extern size_t strlcpy(char *__restrict dst, const char *__restrict src,
size_t n) __THROW __nonnull ((1, 2));
+libc_hidden_proto(strlcpy)
#endif
__END_DECLS
+#ifdef UCLIBC_INTERNAL
+/* In the same order and with the same defines */
+libc_hidden_proto(memcpy)
+libc_hidden_proto(memmove)
+#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN
+libc_hidden_proto(memccpy)
+#endif /* SVID. */
+libc_hidden_proto(memset)
+libc_hidden_proto(memcmp)
+libc_hidden_proto(memchr)
+#ifdef __USE_GNU
+libc_hidden_proto(rawmemchr)
+libc_hidden_proto(memrchr)
+#endif
+libc_hidden_proto(strcpy)
+libc_hidden_proto(strncpy)
+libc_hidden_proto(strcat)
+libc_hidden_proto(strncat)
+libc_hidden_proto(strcmp)
+libc_hidden_proto(strncmp)
+libc_hidden_proto(strcoll)
+libc_hidden_proto(strxfrm)
+#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__
+libc_hidden_proto(strcoll_l)
+libc_hidden_proto(strxfrm_l)
+#endif
+#if defined __USE_SVID || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
+libc_hidden_proto(strdup)
+#endif
+#if defined __USE_GNU
+libc_hidden_proto(strndup)
+#endif
+libc_hidden_proto(strchr)
+libc_hidden_proto(strrchr)
+#ifdef __USE_GNU
+libc_hidden_proto(strchrnul)
+#endif
+libc_hidden_proto(strcspn)
+libc_hidden_proto(strspn)
+libc_hidden_proto(strpbrk)
+libc_hidden_proto(strstr)
+libc_hidden_proto(strtok)
+#if 0 /* uClibc: disabled */
+libc_hidden_proto(__strtok_r)
+#endif
+#if defined __USE_POSIX || defined __USE_MISC
+libc_hidden_proto(strtok_r)
+#endif
+#ifdef __USE_GNU
+libc_hidden_proto(strcasestr)
+#endif
+#ifdef __USE_GNU
+libc_hidden_proto(memmem)
+#if 0 /* uClibc: disabled */
+libc_hidden_proto(__mempcpy)
+#endif
+libc_hidden_proto(mempcpy)
+#endif
+libc_hidden_proto(strlen)
+#ifdef __USE_GNU
+libc_hidden_proto(strnlen)
+#endif
+libc_hidden_proto(strerror)
+/* TODO: insert strerror_r mess here */
+#if 0 /* uClibc: disabled */
+libc_hidden_proto(__bzero)
+#endif
+#ifdef __USE_BSD
+/* No libc_hidden_proto for bcopy etc., since uClibc doesn't itself use the
+ legacy functions. */
+libc_hidden_proto(ffs)
+#if 0 /*def __USE_GNU*/
+libc_hidden_proto(ffsl)
+# ifdef __GNUC__
+libc_hidden_proto(ffsll)
+# endif
+# endif
+libc_hidden_proto(strcasecmp)
+libc_hidden_proto(strncasecmp)
+#endif /* Use BSD. */
+#if defined __USE_GNU && defined __UCLIBC_HAS_XLOCALE__
+libc_hidden_proto(strcasecmp_l)
+libc_hidden_proto(strncasecmp_l)
+#endif
+#ifdef __USE_BSD
+libc_hidden_proto(strsep)
+#endif
+#ifdef __USE_GNU
+#if 0
+libc_hidden_proto(strverscmp)
+#endif
+libc_hidden_proto(strsignal)
+#if 0 /* uClibc: disabled */
+libc_hidden_proto(__stpcpy)
+#endif
+libc_hidden_proto(stpcpy)
+#if 0 /* uClibc: disabled */
+libc_hidden_proto(__stpncpy)
+#endif
+libc_hidden_proto(stpncpy)
+#if 0 /* uClibc does not support strfry or memfrob. */
+libc_hidden_proto(strfry)
+libc_hidden_proto(memfrob)
+#endif
+# ifndef basename
+libc_hidden_proto(basename)
+# endif
+#endif
+#ifdef __USE_BSD
+libc_hidden_proto(strlcat)
+libc_hidden_proto(strlcpy)
+#endif
+#endif
+
+
#endif /* string.h */
diff --git a/include/strings.h b/include/strings.h
index 107c53a4f..31e620673 100644
--- a/include/strings.h
+++ b/include/strings.h
@@ -90,6 +90,10 @@ extern int strncasecmp (__const char *__s1, __const char *__s2, size_t __n)
__END_DECLS
+#ifdef UCLIBC_INTERNAL
+#error "<strings.h> should not be included from libc."
+#endif
+
#endif /* string.h */
#endif /* strings.h */
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index 950183e46..6ebb4a3b4 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -55,7 +55,7 @@ unsigned long __dl_runtime_resolve(unsigned long sym_index,
symname = strtab + sym->st_name;
new_addr = (unsigned long) _dl_find_hash(symname,
- tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
if (unlikely(!new_addr)) {
_dl_dprintf(2, "%s: can't resolve symbol '%s' in lib '%s'.\n",
_dl_progname, symname, tpnt->libname);
@@ -144,8 +144,8 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
struct elf_resolve *tpnt_tls = tpnt;
if (ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_LOCAL) {
- _dl_find_hash2((strtab + symtab[symtab_index].st_name),
- _dl_symbol_tables, NULL, 1, &sym_tls, &tpnt_tls);
+ _dl_find_hash((strtab + symtab[symtab_index].st_name),
+ _dl_symbol_tables, NULL, 1, &sym_tls);
}
switch (reloc_type)
@@ -259,12 +259,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
}
else if (sym->st_shndx == SHN_COMMON) {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
else if (ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
*got_entry != sym->st_value && tmp_lazy) {
@@ -276,7 +276,7 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt, int lazy)
}
else {
*got_entry = (unsigned long) _dl_find_hash(strtab +
- sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT);
+ sym->st_name, tpnt->symbol_scope, tpnt, ELF_RTYPE_CLASS_PLT, NULL);
}
got_entry++;
diff --git a/libc/inet/resolv.c b/libc/inet/resolv.c
index b09684ce4..6d6d18a96 100644
--- a/libc/inet/resolv.c
+++ b/libc/inet/resolv.c
@@ -136,7 +136,6 @@
#define __FORCE_GLIBC
#include <features.h>
#include <string.h>
-#include <strings.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
diff --git a/libc/inet/rpc/ruserpass.c b/libc/inet/rpc/ruserpass.c
index 0adcbf1d3..97f1284b3 100644
--- a/libc/inet/rpc/ruserpass.c
+++ b/libc/inet/rpc/ruserpass.c
@@ -40,7 +40,6 @@
#include <stdio_ext.h>
#include <stdlib.h>
#include <string.h>
-#include <strings.h>
#include <unistd.h>
libc_hidden_proto(strcat)
diff --git a/libc/misc/internals/tempname.c b/libc/misc/internals/tempname.c
index dc125020b..0883259bd 100644
--- a/libc/misc/internals/tempname.c
+++ b/libc/misc/internals/tempname.c
@@ -45,8 +45,8 @@
#include <sys/time.h>
#include "tempname.h"
-libc_hidden_proto(strlen)
-libc_hidden_proto(strcmp)
+/* Experimentally off - libc_hidden_proto(strlen) */
+/* Experimentally off - libc_hidden_proto(strcmp) */
libc_hidden_proto(sprintf)
libc_hidden_proto(mkdir)
libc_hidden_proto(open)
diff --git a/libc/misc/regex/regex.c b/libc/misc/regex/regex.c
index 192034b4e..f39492bdf 100644
--- a/libc/misc/regex/regex.c
+++ b/libc/misc/regex/regex.c
@@ -36,7 +36,6 @@
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
-#include <strings.h>
#include <stdlib.h>
#ifdef __UCLIBC_HAS_WCHAR__
#define RE_ENABLE_I18N
diff --git a/libc/misc/time/time.c b/libc/misc/time/time.c
index 93afa9b68..b5278bce1 100644
--- a/libc/misc/time/time.c
+++ b/libc/misc/time/time.c
@@ -133,7 +133,6 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-#include <strings.h>
#include <time.h>
#include <sys/time.h>
#include <limits.h>
diff --git a/libc/misc/wchar/wchar.c b/libc/misc/wchar/wchar.c
index 32ad41ee6..64bab37e0 100644
--- a/libc/misc/wchar/wchar.c
+++ b/libc/misc/wchar/wchar.c
@@ -1191,7 +1191,6 @@ typedef struct {
#include <iconv.h>
#include <string.h>
-#include <strings.h>
#include <endian.h>
#include <byteswap.h>
diff --git a/libc/stdlib/realpath.c b/libc/stdlib/realpath.c
index aae8580a5..b28d6f07e 100644
--- a/libc/stdlib/realpath.c
+++ b/libc/stdlib/realpath.c
@@ -14,7 +14,6 @@
#include <unistd.h>
#include <stdio.h>
#include <string.h>
-#include <strings.h>
#include <limits.h> /* for PATH_MAX */
#include <sys/param.h> /* for MAXPATHLEN */
#include <errno.h>
diff --git a/libc/sysdeps/linux/common/gethstnm.c b/libc/sysdeps/linux/common/gethstnm.c
deleted file mode 100644
index fc5a72c8d..000000000
--- a/libc/sysdeps/linux/common/gethstnm.c
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
- *
- * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
- */
-
-#include <string.h>
-#include <unistd.h>
-#include <sys/utsname.h>
-#include <errno.h>
-
-libc_hidden_proto(gethostname)
-
-libc_hidden_proto(strlen)
-libc_hidden_proto(strcpy)
-libc_hidden_proto(uname)
-
-int
-gethostname(char *name, size_t len)
-{
- struct utsname uts;
-
- if (name == NULL) {
- __set_errno(EINVAL);
- return -1;
- }
-
- if (uname(&uts) == -1) return -1;
-
- if (strlen(uts.nodename)+1 > len) {
- __set_errno(EINVAL);
- return -1;
- }
- strcpy(name, uts.nodename);
- return 0;
-}
-libc_hidden_def(gethostname)
diff --git a/libc/sysdeps/linux/mips/__syscall_error.c b/libc/sysdeps/linux/mips/__syscall_error.c
new file mode 100644
index 000000000..5e109a83b
--- /dev/null
+++ b/libc/sysdeps/linux/mips/__syscall_error.c
@@ -0,0 +1,18 @@
+/* Wrapper for setting errno.
+ *
+ * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
+ *
+ * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
+ */
+
+#include <errno.h>
+#include <features.h>
+
+/* This routine is jumped to by all the syscall handlers, to stash
+ * an error number into errno. */
+int __syscall_error(int err_no) attribute_hidden;
+int __syscall_error(int err_no)
+{
+ __set_errno(err_no);
+ return -1;
+}
diff --git a/libc/sysdeps/linux/mips/clone.S b/libc/sysdeps/linux/mips/clone.S
index 716cd993f..03162db43 100644
--- a/libc/sysdeps/linux/mips/clone.S
+++ b/libc/sysdeps/linux/mips/clone.S
@@ -125,3 +125,4 @@ __thread_start:
move a0,v0
jal HIDDEN_JUMPTARGET(_exit)
.end __thread_start
+weak_alias(clone, __clone)
diff --git a/libc/sysdeps/linux/mips/sys/asm.h b/libc/sysdeps/linux/mips/sys/asm.h
index 76f6af3e1..4c8bd9cb2 100644
--- a/libc/sysdeps/linux/mips/sys/asm.h
+++ b/libc/sysdeps/linux/mips/sys/asm.h
@@ -469,5 +469,20 @@ symbol = value
# define MFC0 dmfc0
# define MTC0 dmtc0
#endif
+/* The MIPS archtectures do not have a uniform memory model. Particular
+ platforms may provide additional guarantees - for instance, the R4000
+ LL and SC instructions implicitly perform a SYNC, and the 4K promises
+ strong ordering.
+
+ However, in the absence of those guarantees, we must assume weak ordering
+ and SYNC explicitly where necessary.
+
+ Some obsolete MIPS processors may not support the SYNC instruction. This
+ applies to "true" MIPS I processors; most of the processors which compile
+ using MIPS I implement parts of MIPS II. */
+
+#ifndef MIPS_SYNC
+# define MIPS_SYNC sync
+#endif
#endif /* sys/asm.h */
diff --git a/libpthread/nptl/sysdeps/pthread/sigaction.c b/libpthread/nptl/sysdeps/pthread/sigaction.c
index 54b5d2de4..0877e534f 100644
--- a/libpthread/nptl/sysdeps/pthread/sigaction.c
+++ b/libpthread/nptl/sysdeps/pthread/sigaction.c
@@ -20,21 +20,20 @@
/* This is tricky. GCC doesn't like #include_next in the primary
source file and even if it did, the first #include_next is this
exact file anyway. */
-#ifndef LIBC_SIGACTION
-
#include <pthreadP.h>
+#include <features.h>
+#include <errno.h>
+#include <signal.h>
+extern __typeof(sigaction) __libc_sigaction;
+extern __typeof(sigaction) __sigaction;
/* We use the libc implementation but we tell it to not allow
SIGCANCEL or SIGTIMER to be handled. */
-# define LIBC_SIGACTION 1
-
-# include <sigaction.c>
-
int
-sigaction (int sig, const struct sigaction *act, struct sigaction *oact);
-
-int
-__sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
+__sigaction (sig, act, oact)
+ int sig;
+ const struct sigaction *act;
+ struct sigaction *oact;
{
if (__builtin_expect (sig == SIGCANCEL || sig == SIGSETXID, 0))
{
@@ -47,8 +46,3 @@ __sigaction (int sig, const struct sigaction *act, struct sigaction *oact)
libc_hidden_proto(sigaction)
weak_alias (__sigaction, sigaction)
libc_hidden_weak(sigaction)
-#else
-
-# include_next <sigaction.c>
-
-#endif /* LIBC_SIGACTION */
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
index 8011cc087..b5a21342b 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/Makefile.arch
@@ -5,7 +5,7 @@
# Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
#
-libpthread_SSRC = pt-clone.S pt-vfork.S
+libpthread_SSRC = pt-vfork.S
libpthread_CSRC = pthread_once.c
libc_a_CSRC = fork.c
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h
index b8c5280ab..01c1a2891 100644
--- a/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h
+++ b/libpthread/nptl/sysdeps/unix/sysv/linux/mips/sysdep.h
@@ -75,7 +75,7 @@
#undef INTERNAL_SYSCALL_NCS
#define INTERNAL_SYSCALL_NCS(number, err, nr, args...) \
internal_syscall##nr (= number, , "r" (__v0), err, args)
-
+#undef internal_syscall0
#define internal_syscall0(ncs_init, cs_init, input, err, dummy...) \
({ \
long _sys_result; \
@@ -97,6 +97,7 @@
_sys_result; \
})
+#undef internal_syscall1
#define internal_syscall1(ncs_init, cs_init, input, err, arg1) \
({ \
long _sys_result; \
@@ -119,6 +120,7 @@
_sys_result; \
})
+#undef internal_syscall2
#define internal_syscall2(ncs_init, cs_init, input, err, arg1, arg2) \
({ \
long _sys_result; \
@@ -142,6 +144,7 @@
_sys_result; \
})
+#undef internal_syscall3
#define internal_syscall3(ncs_init, cs_init, input, err, arg1, arg2, arg3)\
({ \
long _sys_result; \
@@ -166,6 +169,7 @@
_sys_result; \
})
+#undef internal_syscall4
#define internal_syscall4(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4)\
({ \
long _sys_result; \
@@ -196,6 +200,7 @@
of GCC 3.4.3, this is sufficient. */
#define FORCE_FRAME_POINTER alloca (4)
+#undef internal_syscall5
#define internal_syscall5(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5)\
({ \
long _sys_result; \
@@ -225,6 +230,7 @@
_sys_result; \
})
+#undef internal_syscall6
#define internal_syscall6(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6)\
({ \
long _sys_result; \
@@ -255,6 +261,7 @@
_sys_result; \
})
+#undef internal_syscall7
#define internal_syscall7(ncs_init, cs_init, input, err, arg1, arg2, arg3, arg4, arg5, arg6, arg7)\
({ \
long _sys_result; \