]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Updated to fedora-glibc-20090414T2104 cvs/fedora-glibc-2_9_90-16
authorJakub Jelinek <jakub@redhat.com>
Tue, 14 Apr 2009 21:18:57 +0000 (21:18 +0000)
committerJakub Jelinek <jakub@redhat.com>
Tue, 14 Apr 2009 21:18:57 +0000 (21:18 +0000)
24 files changed:
ChangeLog
NEWS
fedora/branch.mk
fedora/glibc.spec.in
stdio-common/Makefile
stdio-common/Versions
stdio-common/printf-parse.h
stdio-common/printf-parsemb.c
stdio-common/printf-prs.c
stdio-common/printf.h
stdio-common/reg-modifier.c [new file with mode: 0644]
stdio-common/reg-printf.c
stdio-common/reg-type.c [new file with mode: 0644]
stdio-common/vfprintf.c
sysdeps/powerpc/powerpc32/elf/start.S
sysdeps/powerpc/powerpc64/elf/start.S
sysdeps/sparc/sparc32/elf/start.S
sysdeps/sparc/sparc64/elf/start.S
sysdeps/unix/sysv/linux/kernel-features.h
sysdeps/unix/sysv/linux/preadv.c
sysdeps/unix/sysv/linux/pwritev.c
sysdeps/x86_64/memchr.S
sysdeps/x86_64/rawmemchr.S [new file with mode: 0644]
sysdeps/x86_64/strrchr.S [new file with mode: 0644]

index e3f23e35c1c31468a2c811b0e08876f54c6e2781..645a157aae250c9eebd22fecf4b1b059e704f4f5 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,64 @@
+2009-04-14  Jakub Jelinek  <jakub@redhat.com>
+
+       * sysdeps/powerpc/powerpc32/elf/start.S: Ensure .data is non-empty.
+       * sysdeps/powerpc/powerpc64/elf/start.S: Likewise.
+       * sysdeps/sparc/sparc32/elf/start.S: Likewise.
+       * sysdeps/sparc/sparc64/elf/start.S: Likewise.
+
+2009-04-14  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/unix/sysv/linux/kernel-features.h: SH also has
+       preadv/pwritev.
+
+2009-04-13  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/x86-64/strrchr.S: New file.
+
+2009-04-10  Ulrich Drepper  <drepper@redhat.com>
+
+       * stdio-common/printf.h (struct printf_info): Add user element.
+       New types printf_arginfo_size_function, printf_va_arg_function.
+       Declare register_printf_specifier, register_printf_modifier,
+       register_printf_type.
+       * stdio-common/printf-parse.h (struct printf_spec): Add size element.
+       (union printf_arg): Add pa_user element.
+       Adjust __printf_arginfo_table type.
+       Add __printf_va_arg_table, __printf_modifier_table,
+       __handle_registered_modifier_mb, and __handle_registered_modifier_wc
+       declarations.
+       * stdio-common/printf-parsemb.c: Recognize registered modifiers.
+       If registered arginfo call failed try normal specifier.
+       * stdio-common/printf-prs.c: Pass additional parameter to arginfo
+       function.
+       * stdio-common/Makefile (routines): Add reg-modifier and reg-type.
+       * stdio-common/Versions: Export register_printf_modifier,
+       register_printf_type, and register_printf_specifier for GLIBC_2.10.
+       * stdio-common/reg-modifier.c: New file.
+       * stdio-common/reg-type.c: New file.
+       * stdio-common/reg-printf.c (__register_printf_specifier): New
+       function.  Mostly the old __register_printf_function function but
+       uses locking and type of third parameter changed.
+       (__register_printf_function): Implement using
+       __register_printf_specifier.
+       * stdio-common/vfprintf.c (vfprintf): Collect argument sizes in
+       calls to arginfo functions.  Allocate enough memory for user-defined
+       types.  Call new va_arg functions to get user-defined types.
+       Try installed handlers even for existing format specifiers first.
+
+2009-04-09  Ulrich Drepper  <drepper@redhat.com>
+
+       * sysdeps/x86_64/rawmemchr.S: New file.
+
+       * stdio-common/vfprintf.c (vfprintf): Slightly more compact code.
+       Simplified code and possible copy problem fixed.
+
+       * sysdeps/unix/sysv/linux/preadv.c: Avoid prototype for static
+       function if it is not defined.  Add some necessary casts.
+       * sysdeps/unix/sysv/linux/pwritev.c: Likewise.
+
+       * sysdeps/unix/sysv/linux/kernel-features.h: SPARC and IA64 also
+       have preadv/pwritev in 2.6.30.
+
 2009-04-08  Ulrich Drepper  <drepper@redhat.com>
 
        * malloc/malloc.c (malloc_info): New function.
diff --git a/NEWS b/NEWS
index 74feed6f3b0b0e09b9fb8998546e0d435388c83d..d7e52f89828d971d844cac6ddae881a79bb8989e 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-GNU C Library NEWS -- history of user-visible changes.  2009-4-8
+GNU C Library NEWS -- history of user-visible changes.  2009-4-13
 Copyright (C) 1992-2008, 2009 Free Software Foundation, Inc.
 See the end for copying conditions.
 
@@ -37,7 +37,11 @@ Version 2.10
 
 * New locales: nan_TW@latin, ks_IN
 
-* Faster strlen, strchr, strchrnul, and memchr for x86-64.
+* Faster strlen, strchr, strchrnul, strrchr, memchr, and rawmemchr for x86-64.
+  Implemented by Ulrich Drepper.
+
+* Extended printf hook support.  It is possible to use user-defined types
+  and extend existing format specifiers.
   Implemented by Ulrich Drepper.
 
 \f
index 4c3dc344b6c13988d7d6f2f830bf277c3da0ed7b..3b62c91029aaaccfcc7fc48dc12bc0c988842d86 100644 (file)
@@ -3,5 +3,5 @@ glibc-branch := fedora
 glibc-base := HEAD
 DIST_BRANCH := devel
 COLLECTION := dist-f8
-fedora-sync-date := 2009-04-09 14:22 UTC
-fedora-sync-tag := fedora-glibc-20090409T1422
+fedora-sync-date := 2009-04-14 21:04 UTC
+fedora-sync-tag := fedora-glibc-20090414T2104
index db1124fad986bfef955c6044c79a6415cbf27567..8d22e2f00e6c8ee66d69ce1179240aadaef9b467 100644 (file)
@@ -19,7 +19,7 @@
 Summary: The GNU libc libraries
 Name: glibc
 Version: @glibcversion@
-Release: 15
+Release: 16
 # GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
 # Things that are linked directly into dynamically linked programs
 # and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
@@ -229,31 +229,6 @@ package or when debugging this package.
 %endif
 %endif
 
-mkdir -p override_headers/asm
-cat > override_headers/asm/unistd.h <<EOF
-#ifndef _HACK_ASM_UNISTD_H
-#include_next <asm/unistd.h>
-%ifarch %{ix86}
-#ifndef __NR_preadv
-#define __NR_preadv    333
-#define __NR_pwritev   334
-#endif
-%endif
-%ifarch x86_64
-#ifndef __NR_preadv
-#define __NR_preadv    295
-#define __NR_pwritev   296
-#endif
-%endif
-%ifarch ppc ppc64
-#ifndef __NR_preadv
-#define __NR_preadv    320
-#define __NR_pwritev   321
-#endif
-%endif
-#endif
-EOF
-
 # A lot of programs still misuse memcpy when they have to use
 # memmove. The memcpy implementation below is not tolerant at
 # all.
@@ -342,7 +317,7 @@ mkdir $builddir ; cd $builddir
 build_CFLAGS="$BuildFlags -g -O3 $*"
 CC="$GCC" CXX="$GXX" CFLAGS="$build_CFLAGS" ../configure --prefix=%{_prefix} \
        --enable-add-ons=nptl$AddOns --without-cvs $EnableKernel \
-       --with-headers=`cd ..; pwd`/override_headers:%{_prefix}/include --enable-bind-now \
+       --with-headers=%{_prefix}/include --enable-bind-now \
        --with-tls --with-__thread --build %{nptl_target_cpu}-redhat-linux \
        --host %{nptl_target_cpu}-redhat-linux \
        --disable-profile --enable-experimental-malloc --enable-nss-crypt
@@ -1034,6 +1009,9 @@ rm -f *.filelist*
 %endif
 
 %changelog
+* Tue Apr 14 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-16
+- update from trunk
+
 * Thu Apr  9 2009 Jakub Jelinek <jakub@redhat.com> 2.9.90-15
 - rebuilt with fixed gcc to avoid miscompilation of i586 memmove
 - reenable experimental malloc again
index 6d0b8ab9e141a2cf7cdb6236f6d0c344c0ce88a1..9cbf14385c41da87cb864a6e03d538d6272b21bb 100644 (file)
@@ -27,6 +27,7 @@ routines      :=                                                            \
        ctermid cuserid                                                       \
        _itoa _itowa itoa-digits itoa-udigits itowa-digits                    \
        vfprintf vprintf printf_fp reg-printf printf-prs printf_fphex         \
+       reg-modifier reg-type                                                 \
        printf_size fprintf printf snprintf sprintf asprintf dprintf          \
        vfwprintf vfscanf vfwscanf                                            \
        fscanf scanf sscanf                                                   \
index af693fff52fe20e61872a1371472d0b28b1c90a4..3503a84e6b93de2775b6036fdf7f2c229a6e5775 100644 (file)
@@ -55,6 +55,7 @@ libc {
   }
   GLIBC_2.10 {
     psiginfo;
+    register_printf_modifier; register_printf_type; register_printf_specifier;
   }
   GLIBC_PRIVATE {
     # global variables
index f6ad71cd3badcd32be5d25bd7d8a09d00ff4553f..555ad78f335284f4c611521c1aaeaaa432967d07 100644 (file)
@@ -1,5 +1,5 @@
 /* Internal header for parsing printf format strings.
-   Copyright (C) 1995-1999, 2000, 2002, 2003, 2007
+   Copyright (C) 1995-1999, 2000, 2002, 2003, 2007, 2009
    Free Software Foundation, Inc.
    This file is part of th GNU C Library.
 
@@ -42,6 +42,8 @@ struct printf_spec
     int data_arg_type;         /* Type of first argument.  */
     /* Number of arguments consumed by this format specifier.  */
     size_t ndata_args;
+    /* Size of the parameter for PA_USER type.  */
+    int size;
   };
 
 
@@ -60,6 +62,7 @@ union printf_arg
     const char *pa_string;
     const wchar_t *pa_wstring;
     void *pa_pointer;
+    void *pa_user;
   };
 
 
@@ -83,8 +86,9 @@ read_int (const UCHAR_T * *pstr)
 
 
 /* These are defined in reg-printf.c.  */
-extern printf_arginfo_function **__printf_arginfo_table attribute_hidden;
+extern printf_arginfo_size_function **__printf_arginfo_table attribute_hidden;
 extern printf_function **__printf_function_table attribute_hidden;
+extern printf_va_arg_function **__printf_va_arg_table attribute_hidden;
 
 
 /* Find the next spec in FORMAT, or the end of the string.  Returns
@@ -114,3 +118,18 @@ extern size_t __parse_one_specmb (const unsigned char *format, size_t posn,
 extern size_t __parse_one_specwc (const unsigned int *format, size_t posn,
                                  struct printf_spec *spec,
                                  size_t *max_ref_arg) attribute_hidden;
+
+
+
+/* This variable is defined in reg-modifier.c.  */
+struct printf_modifier_record;
+extern struct printf_modifier_record **__printf_modifier_table
+     attribute_hidden;
+
+/* Handle registered modifiers.  */
+extern int __handle_registered_modifier_mb (const unsigned char **format,
+                                           struct printf_info *info)
+     attribute_hidden;
+extern int __handle_registered_modifier_wc (const unsigned int **format,
+                                           struct printf_info *info)
+     attribute_hidden;
index da6fd3edb0bdde5e38747e753dc5b40b5c4f3d39..efd1eca3a2259856e19ba1616d1ce0e22258a441 100644 (file)
@@ -1,5 +1,5 @@
 /* Helper functions for parsing printf format strings.
-   Copyright (C) 1995-2000,2002,2003,2004,2006 Free Software Foundation, Inc.
+   Copyright (C) 1995-2000,2002-2004,2006,2009 Free Software Foundation, Inc.
    This file is part of th GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 # define INT_T         int
 # define L_(Str)       Str
 # define ISDIGIT(Ch)   isdigit (Ch)
+# define HANDLE_REGISTERED_MODIFIER __handle_registered_modifier_mb
 #else
 # define CHAR_T                wchar_t
 # define UCHAR_T       unsigned int
 # define INT_T         wint_t
 # define L_(Str)       L##Str
 # define ISDIGIT(Ch)   iswdigit (Ch)
+# define HANDLE_REGISTERED_MODIFIER __handle_registered_modifier_wc
 #endif
 
 #include "printf-parse.h"
@@ -223,72 +225,79 @@ __parse_one_specmb (const UCHAR_T *format, size_t posn,
   spec->info.is_short = 0;
   spec->info.is_long = 0;
   spec->info.is_char = 0;
-
-  switch (*format++)
-    {
-    case L_('h'):
-      /* ints are short ints or chars.  */
-      if (*format != L_('h'))
-       spec->info.is_short = 1;
-      else
-       {
-         ++format;
-         spec->info.is_char = 1;
-       }
-      break;
-    case L_('l'):
-      /* ints are long ints.  */
-      spec->info.is_long = 1;
-      if (*format != L_('l'))
+  spec->info.user = 0;
+
+  if (__builtin_expect (__printf_modifier_table == NULL, 1)
+      || __printf_modifier_table[*format] == NULL
+      || HANDLE_REGISTERED_MODIFIER (&format, &spec->info) != 0)
+    switch (*format++)
+      {
+      case L_('h'):
+       /* ints are short ints or chars.  */
+       if (*format != L_('h'))
+         spec->info.is_short = 1;
+       else
+         {
+           ++format;
+           spec->info.is_char = 1;
+         }
        break;
-      ++format;
-      /* FALLTHROUGH */
-    case L_('L'):
-      /* doubles are long doubles, and ints are long long ints.  */
-    case L_('q'):
-      /* 4.4 uses this for long long.  */
-      spec->info.is_long_double = 1;
-      break;
-    case L_('z'):
-    case L_('Z'):
-      /* ints are size_ts.  */
-      assert (sizeof (size_t) <= sizeof (unsigned long long int));
+      case L_('l'):
+       /* ints are long ints.  */
+       spec->info.is_long = 1;
+       if (*format != L_('l'))
+         break;
+       ++format;
+       /* FALLTHROUGH */
+      case L_('L'):
+       /* doubles are long doubles, and ints are long long ints.  */
+      case L_('q'):
+       /* 4.4 uses this for long long.  */
+       spec->info.is_long_double = 1;
+       break;
+      case L_('z'):
+      case L_('Z'):
+       /* ints are size_ts.  */
+       assert (sizeof (size_t) <= sizeof (unsigned long long int));
 #if LONG_MAX != LONG_LONG_MAX
-      spec->info.is_long_double = sizeof (size_t) > sizeof (unsigned long int);
+       spec->info.is_long_double = (sizeof (size_t)
+                                    > sizeof (unsigned long int));
 #endif
-      spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
-      break;
-    case L_('t'):
-      assert (sizeof (ptrdiff_t) <= sizeof (long long int));
+       spec->info.is_long = sizeof (size_t) > sizeof (unsigned int);
+       break;
+      case L_('t'):
+       assert (sizeof (ptrdiff_t) <= sizeof (long long int));
 #if LONG_MAX != LONG_LONG_MAX
-      spec->info.is_long_double = (sizeof (ptrdiff_t) > sizeof (long int));
+       spec->info.is_long_double = (sizeof (ptrdiff_t) > sizeof (long int));
 #endif
-      spec->info.is_long = sizeof (ptrdiff_t) > sizeof (int);
-      break;
-    case L_('j'):
-      assert (sizeof (uintmax_t) <= sizeof (unsigned long long int));
+       spec->info.is_long = sizeof (ptrdiff_t) > sizeof (int);
+       break;
+      case L_('j'):
+       assert (sizeof (uintmax_t) <= sizeof (unsigned long long int));
 #if LONG_MAX != LONG_LONG_MAX
-      spec->info.is_long_double = (sizeof (uintmax_t)
-                                  > sizeof (unsigned long int));
+       spec->info.is_long_double = (sizeof (uintmax_t)
+                                    > sizeof (unsigned long int));
 #endif
-      spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int);
-      break;
-    default:
-      /* Not a recognized modifier.  Backup.  */
-      --format;
-      break;
-    }
+       spec->info.is_long = sizeof (uintmax_t) > sizeof (unsigned int);
+       break;
+      default:
+       /* Not a recognized modifier.  Backup.  */
+       --format;
+       break;
+      }
 
   /* Get the format specification.  */
   spec->info.spec = (wchar_t) *format++;
-  if (__builtin_expect (__printf_function_table != NULL, 0)
-      && spec->info.spec <= UCHAR_MAX
-      && __printf_arginfo_table[spec->info.spec] != NULL)
-    /* We don't try to get the types for all arguments if the format
-       uses more than one.  The normal case is covered though.  */
-    spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
-      (&spec->info, 1, &spec->data_arg_type);
-  else
+  spec->size = -1;
+  if (__builtin_expect (__printf_function_table == NULL, 1)
+      || spec->info.spec > UCHAR_MAX
+      || __printf_arginfo_table[spec->info.spec] == NULL
+      /* We don't try to get the types for all arguments if the format
+        uses more than one.  The normal case is covered though.  If
+        the call returns -1 we continue with the normal specifiers.  */
+      || (spec->ndata_args = (*__printf_arginfo_table[spec->info.spec])
+         (&spec->info, 1, &spec->data_arg_type,
+          &spec->size)) < 0)
     {
       /* Find the data argument types of a built-in spec.  */
       spec->ndata_args = 1;
index aabc9ed85a43308fb25f39255486e248211c48e5..e8d84b3be0f4b7b01fc8dcb351e9cad29918c08e 100644 (file)
@@ -1,5 +1,5 @@
-/* Copyright (C) 1991, 1992, 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2005,
-   2007 Free Software Foundation, Inc.
+/* Copyright (C) 1991, 1992, 1995, 1996, 1999, 2000, 2002-2005, 2007, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -97,7 +97,8 @@ parse_printf_format (fmt, n, argtypes)
            /* We have more than one argument for this format spec.  We must
                call the arginfo function again to determine all the types.  */
            (void) (*__printf_arginfo_table[spec.info.spec])
-             (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg]);
+             (&spec.info, n - spec.data_arg, &argtypes[spec.data_arg],
+              &spec.size);
            break;
          }
     }
index 360cdcce1d21fa903b9579e91fff0e4529716ca1..a11af022748f127f953c6844a4aadda32e065f10 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991-1993,1995-1999,2000,2001,2006
+/* Copyright (C) 1991-1993,1995-2001,2006,2009
        Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -29,6 +29,7 @@ __BEGIN_DECLS
 #define        __need_size_t
 #define __need_wchar_t
 #include <stddef.h>
+#include <stdarg.h>
 
 
 struct printf_info
@@ -48,6 +49,8 @@ struct printf_info
   unsigned int is_char:1;      /* hh flag.  */
   unsigned int wide:1;         /* Nonzero for wide character streams.  */
   unsigned int i18n:1;         /* I flag.  */
+  unsigned int __pad:4;                /* Unused so far.  */
+  unsigned short int user;     /* Bits for user-installed modifiers.  */
   wchar_t pad;                 /* Padding character.  */
 };
 
@@ -68,18 +71,55 @@ typedef int printf_function (FILE *__stream,
 
 /* Type of a printf specifier-arginfo function.
    INFO gives information about the format specification.
-   N, ARGTYPES, and return value are as for parse_printf_format.  */
+   N, ARGTYPES, *SIZE has to contain the size of the parameter for
+   user-defined types, and return value are as for parse_printf_format
+   except that -1 should be returned if the handler cannot handle
+   this case.  This allows to partially overwrite the functionality
+   of existing format specifiers.  */
+
+typedef int printf_arginfo_size_function (__const struct printf_info *__info,
+                                         size_t __n, int *__argtypes,
+                                         int *__size);
+
+/* Old version of 'printf_arginfo_function' without a SIZE parameter.  */
 
 typedef int printf_arginfo_function (__const struct printf_info *__info,
                                     size_t __n, int *__argtypes);
 
+/* Type of a function to get a value of a user-defined from the
+   variable argument list.  */
+typedef void printf_va_arg_function (void *__mem, va_list *__ap);
+
 
 /* Register FUNC to be called to format SPEC specifiers; ARGINFO must be
    specified to determine how many arguments a SPEC conversion requires and
    what their types are.  */
 
+extern int register_printf_specifier (int __spec, printf_function __func,
+                                     printf_arginfo_size_function __arginfo)
+  __THROW;
+
+
+/* Obsolete interface similar to register_printf_specifier.  It can only
+   handle basic data types because the ARGINFO callback does not return
+   information on the size of the user-defined type.  */
+
 extern int register_printf_function (int __spec, printf_function __func,
-                                    printf_arginfo_function __arginfo);
+                                    printf_arginfo_function __arginfo)
+  __THROW __attribute_deprecated__;
+
+
+/* Register a new modifier character sequence.  If the call succeeds
+   it returns a positive value representing the bit set in the USER
+   field in 'struct printf_info'.  */
+
+extern int register_printf_modifier (wchar_t *__str) __wur __THROW;
+
+
+/* Register variable argument handler for user type.  The return value
+   is to be used in ARGINFO functions to signal the use of the
+   type.  */
+extern int register_printf_type (printf_va_arg_function __fct) __wur __THROW;
 
 
 /* Parse FMT, and fill in N elements of ARGTYPES with the
@@ -100,7 +140,8 @@ extern size_t parse_printf_format (__const char *__restrict __fmt, size_t __n,
 /* Codes returned by `parse_printf_format' for basic types.
 
    These values cover all the standard format specifications.
-   Users can add new values after PA_LAST for their own types.  */
+   Users can reserve new values after PA_LAST for their own types
+   using 'register_printf_type'.  */
 
 enum
 {                              /* C type: */
diff --git a/stdio-common/reg-modifier.c b/stdio-common/reg-modifier.c
new file mode 100644 (file)
index 0000000..69bb2ef
--- /dev/null
@@ -0,0 +1,202 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <limits.h>
+#include <printf.h>
+#include <wchar.h>
+#include <bits/libc-lock.h>
+
+
+struct printf_modifier_record
+{
+  struct printf_modifier_record *next;
+  int bit;
+  wchar_t str[0];
+};
+
+struct printf_modifier_record **__printf_modifier_table attribute_hidden;
+
+__libc_lock_define_initialized (static, lock)
+
+/* Bits to hand out.  */
+static int next_bit;
+
+
+int
+__register_printf_modifier (wchar_t *str)
+{
+  if (str[0] == L'\0')
+    {
+    einval:
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  wchar_t *wc = str;
+  while (*wc != L'\0')
+    if (*wc < 0 || *wc > (wchar_t) UCHAR_MAX)
+      goto einval;
+    else
+      ++wc;
+
+  if (next_bit / 8 == sizeof (((struct printf_info *) NULL)->user))
+    {
+      __set_errno (ENOSPC);
+      return -1;
+    }
+
+  int result = -1;
+  __libc_lock_lock (lock);
+
+  if (__printf_modifier_table == NULL)
+    {
+      __printf_modifier_table = calloc (UCHAR_MAX,
+                                       sizeof (*__printf_modifier_table));
+      if (__printf_modifier_table == NULL)
+       goto out;
+    }
+
+  /* Create enough room for the string.  But we don't need the first
+     character. */
+  struct printf_modifier_record *newp = malloc (sizeof (*newp)
+                                               + ((wc - str)
+                                                  * sizeof (wchar_t)));
+  if (newp == NULL)
+    goto out;
+
+  newp->next = __printf_modifier_table[(unsigned char) *str];
+  newp->bit = 1 << next_bit++;
+  __wmemcpy (newp->str, str + 1, wc - str);
+
+  __printf_modifier_table[(unsigned char) *str] = newp;
+
+  result = newp->bit;
+
+ out:
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+weak_alias (__register_printf_modifier, register_printf_modifier)
+
+
+#include <stdio.h>
+int
+attribute_hidden
+__handle_registered_modifier_mb (const unsigned char **format,
+                                struct printf_info *info)
+{
+  struct printf_modifier_record *runp = __printf_modifier_table[**format];
+
+  int best_bit = 0;
+  int best_len = 0;
+  const unsigned char *best_cp = NULL;
+
+  while (runp != NULL)
+    {
+      const unsigned char *cp = *format + 1;
+      wchar_t *fcp = runp->str;
+
+      while (*cp != '\0' && *fcp != L'\0')
+       if (*cp != *fcp)
+         break;
+       else
+         ++cp, ++fcp;
+
+      if (*fcp == L'\0' && cp - *format > best_len)
+       {
+         best_cp = cp;
+         best_len = cp - *format;
+         best_bit = runp->bit;
+       }
+
+      runp = runp->next;
+    }
+
+  if (best_bit != 0)
+    {
+      info->user |= best_bit;
+      *format = best_cp;
+      return 0;
+    }
+
+  return 1;
+}
+
+
+int
+attribute_hidden
+__handle_registered_modifier_wc (const unsigned int **format,
+                                struct printf_info *info)
+{
+  struct printf_modifier_record *runp = __printf_modifier_table[**format];
+
+  int best_bit = 0;
+  int best_len = 0;
+  const unsigned int *best_cp = NULL;
+
+  while (runp != NULL)
+    {
+      const unsigned int *cp = *format + 1;
+      wchar_t *fcp = runp->str;
+
+      while (*cp != '\0' && *fcp != L'\0')
+       if (*cp != *fcp)
+         break;
+       else
+         ++cp, ++fcp;
+
+      if (*fcp == L'\0' && cp - *format > best_len)
+       {
+         best_cp = cp;
+         best_len = cp - *format;
+         best_bit = runp->bit;
+       }
+
+      runp = runp->next;
+    }
+
+  if (best_bit != 0)
+    {
+      info->user |= best_bit;
+      *format = best_cp;
+      return 0;
+    }
+
+  return 1;
+}
+
+
+libc_freeres_fn (free_mem)
+{
+  if (__printf_modifier_table != NULL)
+    {
+      for (int i = 0; i < UCHAR_MAX; ++i)
+       {
+         struct printf_modifier_record *runp = __printf_modifier_table[i];
+         while (runp != NULL)
+           {
+             struct printf_modifier_record *oldp = runp;
+             runp = runp->next;
+             free (oldp);
+           }
+       }
+      free (__printf_modifier_table);
+    }
+}
index dbb6234e5f701d403902f92c6310f64e78036108..b5cab679de0aec6a7f24df831187908af45abba0 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1991,1996,1997,2002,2003,2004 Free Software Foundation, Inc.
+/* Copyright (C) 1991,1996,1997,2002-2004,2009 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
 #include <printf.h>
 #include <stddef.h>
 #include <stdlib.h>
+#include <bits/libc-lock.h>
+
 
 /* Array of functions indexed by format character.  */
-libc_freeres_ptr (printf_arginfo_function **__printf_arginfo_table)
+libc_freeres_ptr (printf_arginfo_size_function **__printf_arginfo_table)
   attribute_hidden;
 printf_function **__printf_function_table attribute_hidden;
 
+__libc_lock_define_initialized (static, lock)
+
+int __register_printf_specifier (int, printf_function,
+                                printf_arginfo_size_function);
 int __register_printf_function (int, printf_function,
-                               printf_arginfo_function) __THROW;
+                               printf_arginfo_function);
+
 
 /* Register FUNC to be called to format SPEC specifiers.  */
 int
-__register_printf_function (spec, converter, arginfo)
+__register_printf_specifier (spec, converter, arginfo)
      int spec;
      printf_function converter;
-     printf_arginfo_function arginfo;
+     printf_arginfo_size_function arginfo;
 {
   if (spec < 0 || spec > (int) UCHAR_MAX)
     {
@@ -43,12 +50,19 @@ __register_printf_function (spec, converter, arginfo)
       return -1;
     }
 
+  int result = 0;
+  __libc_lock_lock (lock);
+
   if (__printf_function_table == NULL)
     {
-      __printf_arginfo_table = (printf_arginfo_function **)
+      __printf_arginfo_table = (printf_arginfo_size_function **)
        calloc (UCHAR_MAX + 1, sizeof (void *) * 2);
       if (__printf_arginfo_table == NULL)
-       return -1;
+       {
+         result = -1;
+         goto out;
+       }
+
       __printf_function_table = (printf_function **)
        (__printf_arginfo_table + UCHAR_MAX + 1);
     }
@@ -56,6 +70,22 @@ __register_printf_function (spec, converter, arginfo)
   __printf_function_table[spec] = converter;
   __printf_arginfo_table[spec] = arginfo;
 
-  return 0;
+ out:
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+weak_alias (__register_printf_specifier, register_printf_specifier)
+
+
+/* Register FUNC to be called to format SPEC specifiers.  */
+int
+__register_printf_function (spec, converter, arginfo)
+     int spec;
+     printf_function converter;
+     printf_arginfo_function arginfo;
+{
+  return __register_printf_specifier (spec, converter,
+                                     (printf_arginfo_size_function*) arginfo);
 }
 weak_alias (__register_printf_function, register_printf_function)
diff --git a/stdio-common/reg-type.c b/stdio-common/reg-type.c
new file mode 100644 (file)
index 0000000..7a96b28
--- /dev/null
@@ -0,0 +1,62 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <errno.h>
+#include <printf.h>
+#include <stdlib.h>
+#include <bits/libc-lock.h>
+
+
+/* Array of functions indexed by format character.  */
+libc_freeres_ptr (printf_va_arg_function **__printf_va_arg_table)
+  attribute_hidden;
+
+__libc_lock_define_initialized (static, lock);
+
+/* Last type allocated.  */
+static int pa_next_type = PA_LAST;
+
+
+int
+__register_printf_type (printf_va_arg_function fct)
+{
+  int result = -1;
+  __libc_lock_lock (lock);
+
+  if (__printf_va_arg_table == NULL)
+    {
+      __printf_va_arg_table = (printf_va_arg_function **)
+       calloc (0x100 - PA_LAST, sizeof (void *));
+      if (__printf_va_arg_table == NULL)
+       goto out;
+    }
+
+  if (pa_next_type == 0x100)
+    __set_errno (ENOSPC);
+  else
+    {
+      result = pa_next_type++;
+      __printf_va_arg_table[result - PA_LAST] = fct;
+    }
+
+ out:
+  __libc_lock_unlock (lock);
+
+  return result;
+}
+weak_alias (__register_printf_type, register_printf_type)
index 5d5bb5e5783d5f93e758d1fca0b8ea1ec94595f3..38ba8ffdcd6f6566e4a0a15510754ce8fbaddce5 100644 (file)
@@ -1,5 +1,4 @@
-/* Copyright (C) 1991-2002, 2003, 2004, 2005, 2006, 2007, 2008
-   Free Software Foundation, Inc.
+/* Copyright (C) 1991-2008, 2009   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -239,7 +238,7 @@ vfprintf (FILE *s, const CHAR_T *format, va_list ap)
   /* This table maps a character into a number representing a
      class.  In each step there is a destination label for each
      class.  */
-  static const int jump_table[] =
+  static const uint8_t jump_table[] =
   {
     /* ' ' */  1,            0,            0, /* '#' */  4,
               0, /* '%' */ 14,            0, /* '\''*/  6,
@@ -1631,6 +1630,7 @@ do_positional:
     size_t nargs = 0;
     int *args_type;
     union printf_arg *args_value = NULL;
+    int *args_size;
 
     /* Positional parameters refer to arguments directly.  This could
        also determine the maximum number of arguments.  Track the
@@ -1663,24 +1663,10 @@ do_positional:
          {
            /* Extend the array of format specifiers.  */
            struct printf_spec *old = specs;
+           specs = extend_alloca (specs, nspecs_max, 2 * nspecs_max);
 
-           nspecs_max *= 2;
-           specs = alloca (nspecs_max * sizeof (struct printf_spec));
-
-           if (specs == &old[nspecs])
-             /* Stack grows up, OLD was the last thing allocated;
-                extend it.  */
-             nspecs_max += nspecs_max / 2;
-           else
-             {
-               /* Copy the old array's elements to the new space.  */
-               memcpy (specs, old, nspecs * sizeof (struct printf_spec));
-               if (old == &specs[nspecs])
-                 /* Stack grows down, OLD was just below the new
-                    SPECS.  We can use that space when the new space
-                    runs out.  */
-                 nspecs_max += nspecs_max / 2;
-             }
+           /* Copy the old array's elements to the new space.  */
+           memmove (specs, old, nspecs * sizeof (struct printf_spec));
          }
 
        /* Parse the format specifier.  */
@@ -1699,6 +1685,7 @@ do_positional:
     memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
            nargs * sizeof (int));
     args_value = alloca (nargs * sizeof (union printf_arg));
+    args_size = alloca (nargs * sizeof (int));
 
     /* XXX Could do sanity check here: If any element in ARGS_TYPE is
        still zero after this loop, format is invalid.  For now we
@@ -1719,8 +1706,10 @@ do_positional:
          {
          case 0:               /* No arguments.  */
            break;
-         case 1:               /* One argument; we already have the type.  */
+         case 1:               /* One argument; we already have the
+                                  type and size.  */
            args_type[specs[cnt].data_arg] = specs[cnt].data_arg_type;
+           args_size[specs[cnt].data_arg] = specs[cnt].size;
            break;
          default:
            /* We have more than one argument for this format spec.
@@ -1728,7 +1717,8 @@ do_positional:
               all the types.  */
            (void) (*__printf_arginfo_table[specs[cnt].info.spec])
              (&specs[cnt].info,
-              specs[cnt].ndata_args, &args_type[specs[cnt].data_arg]);
+              specs[cnt].ndata_args, &args_type[specs[cnt].data_arg],
+              &args_size[specs[cnt].data_arg]);
            break;
          }
       }
@@ -1743,13 +1733,21 @@ do_positional:
          args_value[cnt].mem = va_arg (ap_save, type);                       \
          break
 
-       T (PA_CHAR, pa_int, int); /* Promoted.  */
        T (PA_WCHAR, pa_wchar, wint_t);
-       T (PA_INT|PA_FLAG_SHORT, pa_int, int); /* Promoted.  */
+       case PA_CHAR:                           /* Promoted.  */
+       case PA_INT|PA_FLAG_SHORT:              /* Promoted.  */
+#if LONG_MAX == INT_MAX
+       case PA_INT|PA_FLAG_LONG:
+#endif
        T (PA_INT, pa_int, int);
-       T (PA_INT|PA_FLAG_LONG, pa_long_int, long int);
+#if LONG_MAX == LONG_LONG_MAX
+       case PA_INT|PA_FLAG_LONG:
+#endif
        T (PA_INT|PA_FLAG_LONG_LONG, pa_long_long_int, long long int);
-       T (PA_FLOAT, pa_double, double);        /* Promoted.  */
+#if LONG_MAX != INT_MAX && LONG_MAX != LONG_LONG_MAX
+# error "he?"
+#endif
+       case PA_FLOAT:                          /* Promoted.  */
        T (PA_DOUBLE, pa_double, double);
        case PA_DOUBLE|PA_FLAG_LONG_DOUBLE:
          if (__ldbl_is_dbl)
@@ -1760,13 +1758,20 @@ do_positional:
          else
            args_value[cnt].pa_long_double = va_arg (ap_save, long double);
          break;
-       T (PA_STRING, pa_string, const char *);
-       T (PA_WSTRING, pa_wstring, const wchar_t *);
+       case PA_STRING:                         /* All pointers are the same */
+       case PA_WSTRING:                        /* All pointers are the same */
        T (PA_POINTER, pa_pointer, void *);
 #undef T
        default:
          if ((args_type[cnt] & PA_FLAG_PTR) != 0)
            args_value[cnt].pa_pointer = va_arg (ap_save, void *);
+         else if (__builtin_expect (__printf_va_arg_table != NULL, 0)
+                  && __printf_va_arg_table[args_type[cnt] - PA_LAST] != NULL)
+           {
+             args_value[cnt].pa_user = alloca (args_size[cnt]);
+             (*__printf_va_arg_table[args_type[cnt] - PA_LAST])
+               (args_value[cnt].pa_user, &ap_save);
+           }
          else
            args_value[cnt].pa_long_double = 0.0;
          break;
@@ -1870,6 +1875,40 @@ do_positional:
        /* Process format specifiers.  */
        while (1)
          {
+           extern printf_function **__printf_function_table;
+           int function_done;
+
+           if (spec <= UCHAR_MAX
+               && __printf_function_table != NULL
+               && __printf_function_table[(size_t) spec] != NULL)
+             {
+               const void **ptr = alloca (specs[nspecs_done].ndata_args
+                                          * sizeof (const void *));
+
+               /* Fill in an array of pointers to the argument values.  */
+               for (unsigned int i = 0; i < specs[nspecs_done].ndata_args;
+                    ++i)
+                 ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
+
+               /* Call the function.  */
+               function_done = __printf_function_table[(size_t) spec]
+                 (s, &specs[nspecs_done].info, ptr);
+
+               if (function_done != -2)
+                 {
+                   /* If an error occurred we don't have information
+                      about # of chars.  */
+                   if (function_done < 0)
+                     {
+                       done = -1;
+                       goto all_done;
+                     }
+
+                   done_add (function_done);
+                   break;
+                 }
+             }
+
            JUMP (spec, step4_jumps);
 
            process_arg ((&specs[nspecs_done]));
@@ -1877,19 +1916,9 @@ do_positional:
 
          LABEL (form_unknown):
            {
-             extern printf_function **__printf_function_table;
-             int function_done;
-             printf_function *function;
              unsigned int i;
              const void **ptr;
 
-             function =
-               (__printf_function_table == NULL ? NULL :
-                __printf_function_table[specs[nspecs_done].info.spec]);
-
-             if (function == NULL)
-               function = &printf_unknown;
-
              ptr = alloca (specs[nspecs_done].ndata_args
                            * sizeof (const void *));
 
@@ -1898,7 +1927,8 @@ do_positional:
                ptr[i] = &args_value[specs[nspecs_done].data_arg + i];
 
              /* Call the function.  */
-             function_done = (*function) (s, &specs[nspecs_done].info, ptr);
+             function_done = printf_unknown (s, &specs[nspecs_done].info,
+                                             ptr);
 
              /* If an error occurred we don't have information about #
                 of chars.  */
index bafd2ae00109daa40b574abbb7bf8c0c8d7907a6..a8abdca0c6903d281a29b2bbc36206d5c7fe045c 100644 (file)
@@ -1,5 +1,6 @@
 /* Startup code for programs linked with GNU libc.
-   Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+   Copyright (C) 1998,1999,2000,2001,2002,2003,2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -98,4 +99,5 @@ END(_start)
        .section ".data"
        .globl  __data_start
 __data_start:
+       .long   0
 weak_alias (__data_start, data_start)
index c9119a26248d3f67063ba5d93c7cf7a5832a4dea..e559b878410ef5255aa72e3ae479d1aec27b8883 100644 (file)
@@ -1,5 +1,6 @@
 /* Startup code for programs linked with GNU libc.  PowerPC64 version.
-   Copyright (C) 1998,1999,2000,2001,2002,2003 Free Software Foundation, Inc.
+   Copyright (C) 1998,1999,2000,2001,2002,2003,2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -83,4 +84,5 @@ END(_start)
        .section ".data"
        .globl  __data_start
 __data_start:
+       .long   0
 weak_alias (__data_start, data_start)
index 85adb7322f5b2162c01507d93924b160df6f09b9..7ff4bd68f67961a61323f91b6b181f38edc035ac 100644 (file)
@@ -1,5 +1,6 @@
 /* Startup code for elf32-sparc
-   Copyright (C) 1997, 1998, 2002, 2004, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2002, 2004, 2007, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
 
@@ -96,4 +97,5 @@ _start:
        .data
        .globl  __data_start
 __data_start:
+       .long   0
 weak_alias (__data_start, data_start)
index 650d3d3048d3355033cc2f124f14e760e3cadb3f..406ea0f55e1adda5e41be8e8a5563ffcc1ad96ce 100644 (file)
@@ -1,5 +1,6 @@
 /* Startup code for elf64-sparc
-   Copyright (C) 1997, 1998, 2002, 2004, 2007 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 2002, 2004, 2007, 2009
+   Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
 
@@ -97,4 +98,5 @@ _start:
        .data
        .globl  __data_start
 __data_start:
+       .long   0
 weak_alias (__data_start, data_start)
index 5f1ffdb9c530262feda077df15855ca189bf60d1..2fa8524db9517b71898d0bf83533c9e4b68780b2 100644 (file)
 
 /* Support for preadv and pwritev was added in 2.6.30.  */
 #if __LINUX_KERNEL_VERSION >= 0x02061e \
-    && (defined __i386__ || defined __x86_64__ || defined __powerpc__)
+    && (defined __i386__ || defined __x86_64__ || defined __powerpc__ \
+       || defined __ia64__ || defined __sparc__ && defined __sh__)
 # define __ASSUME_PREADV       1
 # define __ASSUME_PWRITEV      1
 #endif
index e2f823859635d0da0ac1175f43d7316071b29850..0d4a6c380348a667c399c75c4d12cba2eb4fa101 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/syscall.h>
 #include <kernel-features.h>
 
+
 #ifndef PREADV
 # define PREADV preadv
 # define PREADV_REPLACEMENT __atomic_preadv_replacement
 # define OFF_T off_t
 #endif
 
+#ifndef __ASSUME_PREADV
 static ssize_t PREADV_REPLACEMENT (int, __const struct iovec *,
                                   int, OFF_T) internal_function;
+#endif
 
 
 ssize_t
@@ -51,14 +54,16 @@ PREADV (fd, vector, count, offset)
   ssize_t result;
 
   if (SINGLE_THREAD_P)
-    result = INLINE_SYSCALL (preadv, 5, fd, vector, count, offset >> 32,
-                            offset & 0xffffffff);
+    result = INLINE_SYSCALL (preadv, 5, fd, vector, count,
+                            (off_t) ((off64_t) offset >> 32),
+                            (off_t) (offset & 0xffffffff));
   else
     {
       int oldtype = LIBC_CANCEL_ASYNC ();
 
-      result = INLINE_SYSCALL (preadv, 5, fd, vector, count, offset >> 32,
-                              offset & 0xffffffff);
+      result = INLINE_SYSCALL (preadv, 5, fd, vector, count,
+                              (off_t) ((off64_t) offset >> 32),
+                              (off_t) (offset & 0xffffffff));
 
       LIBC_CANCEL_RESET (oldtype);
     }
index df430ffe46e5e6bea1329b64f81539786f24cda1..5c30eae51f06ae98ab247d7aba20184646340e75 100644 (file)
@@ -29,6 +29,7 @@
 #include <sys/syscall.h>
 #include <kernel-features.h>
 
+
 #ifndef PWRITEV
 # define PWRITEV pwritev
 # define PWRITEV_REPLACEMENT __atomic_pwritev_replacement
 # define OFF_T off_t
 #endif
 
+#ifndef __ASSUME_PWRITEV
 static ssize_t PWRITEV_REPLACEMENT (int, __const struct iovec *,
                                    int, OFF_T) internal_function;
+#endif
 
 
 ssize_t
@@ -51,14 +54,16 @@ PWRITEV (fd, vector, count, offset)
   ssize_t result;
 
   if (SINGLE_THREAD_P)
-    result = INLINE_SYSCALL (pwritev, 5, fd, vector, count, offset >> 32,
-                            offset & 0xffffffff);
+    result = INLINE_SYSCALL (pwritev, 5, fd, vector, count,
+                            (off_t) ((off64_t) offset >> 32),
+                            (off_t) (offset & 0xffffffff));
   else
     {
       int oldtype = LIBC_CANCEL_ASYNC ();
 
-      result = INLINE_SYSCALL (pwritev, 5, fd, vector, count, offset >> 32,
-                              offset & 0xffffffff);
+      result = INLINE_SYSCALL (pwritev, 5, fd, vector, count,
+                              (off_t) ((off64_t) offset >> 32),
+                              (off_t) (offset & 0xffffffff));
 
       LIBC_CANCEL_RESET (oldtype);
     }
index 644362d565fd5b4d592296d30da22b8b9c8cba9d..09ba6d4f8dab9244d80e74c45b5505ed705765e4 100644 (file)
@@ -1,5 +1,4 @@
-/* strlen(str) -- determine the length of the string STR.
-   Copyright (C) 2009 Free Software Foundation, Inc.
+/* Copyright (C) 2009 Free Software Foundation, Inc.
    Contributed by Ulrich Drepper <drepper@redhat.com>.
    This file is part of the GNU C Library.
 
diff --git a/sysdeps/x86_64/rawmemchr.S b/sysdeps/x86_64/rawmemchr.S
new file mode 100644 (file)
index 0000000..c3bd771
--- /dev/null
@@ -0,0 +1,54 @@
+/* Copyright (C) 2009 Free Software Foundation, Inc.
+   Contributed by Ulrich Drepper <drepper@redhat.com>.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+
+       .text
+ENTRY (rawmemchr)
+       movd    %esi, %xmm1
+       movq    %rdi, %rcx
+       punpcklbw %xmm1, %xmm1
+       andq    $~15, %rdi
+       punpcklbw %xmm1, %xmm1
+       orl     $0xffffffff, %esi
+       movdqa  (%rdi), %xmm0
+       pshufd  $0, %xmm1, %xmm1
+       subq    %rdi, %rcx
+       pcmpeqb %xmm1, %xmm0
+       shl     %cl, %esi
+       pmovmskb %xmm0, %ecx
+       leaq    16(%rdi), %rdi
+       andl    %esi, %ecx
+       jnz     1f
+
+2:     movdqa  (%rdi), %xmm0
+       leaq    16(%rdi), %rdi
+       pcmpeqb %xmm1, %xmm0
+       pmovmskb %xmm0, %ecx
+       testl   %ecx, %ecx
+       jz      2b
+
+1:     bsfl    %ecx, %ecx
+       leaq    -16(%rcx,%rdi), %rax
+       ret
+END (rawmemchr)
+
+strong_alias (rawmemchr, __rawmemchr)
+libc_hidden_builtin_def (__rawmemchr)
diff --git a/sysdeps/x86_64/strrchr.S b/sysdeps/x86_64/strrchr.S
new file mode 100644 (file)
index 0000000..c75b485
--- /dev/null
@@ -0,0 +1,81 @@
+/* strrchr (str, ch) -- Return pointer to last occurrence of CH in STR.
+   For AMD x86-64.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#include <sysdep.h>
+
+
+       .text
+ENTRY (strrchr)
+       movd    %esi, %xmm1
+       movq    %rdi, %rcx
+       punpcklbw %xmm1, %xmm1
+       andq    $~15, %rdi
+       pxor    %xmm2, %xmm2
+       punpcklbw %xmm1, %xmm1
+       orl     $0xffffffff, %esi
+       movdqa  (%rdi), %xmm0
+       pshufd  $0, %xmm1, %xmm1
+       subq    %rdi, %rcx
+       movdqa  %xmm0, %xmm3
+       leaq    16(%rdi), %rdi
+       pcmpeqb %xmm1, %xmm0
+       pcmpeqb %xmm2, %xmm3
+       shl     %cl, %esi
+       pmovmskb %xmm0, %edx
+       pmovmskb %xmm3, %ecx
+       andl    %esi, %edx
+       andl    %esi, %ecx
+       xorl    %eax, %eax
+       movl    %edx, %esi
+       orl     %ecx, %esi
+       jnz     1f
+
+2:     movdqa  (%rdi), %xmm0
+       leaq    16(%rdi), %rdi
+       movdqa  %xmm0, %xmm3
+       pcmpeqb %xmm1, %xmm0
+       pcmpeqb %xmm2, %xmm3
+       pmovmskb %xmm0, %edx
+       pmovmskb %xmm3, %ecx
+       movl    %edx, %esi
+       orl     %ecx, %esi
+       jz      2b
+
+1:     bsfl    %ecx, %r9d
+       movl    $0xffffffff, %r8d
+       movl    $31, %ecx
+       jnz     5f
+
+       bsrl    %edx, %edx
+       jz      2b
+       leaq    -16(%rdi,%rdx), %rax
+       jmp     2b
+
+5:     subl    %r9d, %ecx
+       shrl    %cl, %r8d
+       andl    %r8d, %edx
+       bsrl    %edx, %edx
+       jz      4f
+       leaq    -16(%rdi,%rdx), %rax
+4:     ret
+END (strrchr)
+
+weak_alias (strrchr, rindex)
+libc_hidden_builtin_def (strrchr)