From patchwork Sat Jul 26 05:57:11 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 2185 Received: (qmail 14657 invoked by alias); 26 Jul 2014 05:57:30 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 14551 invoked by uid 89); 26 Jul 2014 05:57:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pd0-f180.google.com X-Received: by 10.67.30.163 with SMTP id kf3mr23711347pad.110.1406354246607; Fri, 25 Jul 2014 22:57:26 -0700 (PDT) From: Alan Modra To: bug-gnulib@gnu.org, libc-alpha@sourceware.org Cc: Alan Modra Subject: [PATCH 4/5] 64-bit obstack support, part 3 Date: Sat, 26 Jul 2014 15:27:11 +0930 Message-Id: <1406354233-7664-5-git-send-email-amodra@gmail.com> In-Reply-To: <1406354233-7664-1-git-send-email-amodra@gmail.com> References: <1406354233-7664-1-git-send-email-amodra@gmail.com> This finally enables full 64-bit obstack support. Renaming the _obstack_* functions to _obstack2_* is necessary to prevent a shared library using version 1 obstack functions from having these functions overridden by version 2 functions in the main executable. Not all shared libraries are created with as much care as glibc in this regard. Moving __OBSTACK_INTERFACE_VERSION to obstack.h allows glibc to compile obstack.c twice, once to provide version 1 compat functions, and once for 64-bit obstack support. For 32-bit targets where version 1 and version 2 code is ABI compatible, I've put machinery in place so that we only get one copy of the obstack.c functions. * lib/obstack.h (__OBSTACK_INTERFACE_VERSION): Define. (__OBSTACK_ELIDE_CODE): Define. (__OBSTACK_ALIAS_VER2): Define. (__OBSTACK_SIZE_T, __CHUNK_SIZE_T): Define as size_t for version 2. (_obstack_allocated_p, _obstack_begin, _obstack_begin_1, _obstack_free, _obstack_memory_used, _obstack_newchunk): Define for version 2. (_obstack2_begin, _obstack2_begin_1, _obstack2_free, _obstack2_memory_used, _obstack2_newchunk): Declare function aliases. * lib/obstack.c (__OBSTACK_INTERFACE_VERSION): Delete. (ELIDE_CODE): Delete, test __OBSTACK_ELIDE_CODE instead. (_obstack2_begin, _obstack2_begin_1, _obstack2_free, _obstack2_memory_used, _obstack2_newchunk): Emit aliases for glibc. (obstack_alloc_failed_handler, print_and_abort, _obstack_compat): Arrange for libc to emit definitions only for one obstack version. * module/obstack: Add obstack.o to libgnu.a. --- lib/obstack.c | 88 ++++++++++++++++++++++++++----------------------------- lib/obstack.h | 74 ++++++++++++++++++++++++++++++++++++++++++++-- modules/obstack | 1 + 3 files changed, 115 insertions(+), 48 deletions(-) diff --git a/lib/obstack.c b/lib/obstack.c index 98b955e..1ac0e5d 100644 --- a/lib/obstack.c +++ b/lib/obstack.c @@ -25,30 +25,11 @@ # include "obstack.h" #endif -/* NOTE BEFORE MODIFYING THIS FILE: This version number must be - incremented whenever callers compiled using an old obstack.h can no - longer properly call the functions in this obstack.c. */ -#define OBSTACK_INTERFACE_VERSION 1 - -/* Comment out all this code if we are using the GNU C Library, and are not - actually compiling the library itself, and the installed library - supports the same library interface we do. This code is part of the GNU - C Library, but also included in many other GNU distributions. Compiling - and linking in this code is a waste when using the GNU C library - (especially if it is a shared library). Rather than having every GNU - program understand 'configure --with-gnu-libc' and omit the object - files, it is simpler to just do this in the source for each such file. */ - -#include /* Random thing to get __GNU_LIBRARY__. */ -#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 -# include -# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION -# define ELIDE_CODE -# endif -#endif - -#ifndef ELIDE_CODE +/* NOTE BEFORE MODIFYING THIS FILE: __OBSTACK_INTERFACE_VERSION in + obstack.h must be incremented whenever callers compiled using an old + obstack.h can no longer properly call the functions in this file. */ +#ifndef __OBSTACK_ELIDE_CODE # include # include @@ -293,7 +274,7 @@ _obstack_free (struct obstack *h, void *obj) /* obj is not in any of the chunks! */ abort (); } -# ifdef _LIBC +# if defined _LIBC && __OBSTACK_INTERFACE_VERSION == 1 /* Older versions of libc defined both _obstack_free and obstack_free. */ strong_alias (_obstack_free, obstack_free) # endif @@ -311,28 +292,42 @@ _obstack_memory_used (struct obstack *h) return nbytes; } +# ifdef __OBSTACK_ALIAS_VER2 +/* If sizeof(int) == sizeof(size_t) then version 2 obstack code is ABI + compatible with version 1. */ +strong_alias (_obstack_allocated_p, _obstack2_allocated_p) +strong_alias (_obstack_begin, _obstack2_begin) +strong_alias (_obstack_begin_1, _obstack2_begin_1) +strong_alias (_obstack_free, _obstack2_free) +strong_alias (_obstack_memory_used, _obstack2_memory_used) +strong_alias (_obstack_newchunk, _obstack2_newchunk) +libc_hidden_def (_obstack2_newchunk) +# endif + + /* Define the error handler. */ +# if !defined _LIBC || __OBSTACK_INTERFACE_VERSION == 1 /* Exit value used when 'print_and_abort' is used. */ -# ifdef _LIBC +# ifdef _LIBC int obstack_exit_failure = EXIT_FAILURE; -# else -# include "exitfail.h" -# define obstack_exit_failure exit_failure -# endif +# else +# include "exitfail.h" +# define obstack_exit_failure exit_failure +# endif -# ifdef _LIBC -# include -# else -# include "gettext.h" -# endif -# ifndef _ -# define _(msgid) gettext (msgid) -# endif +# ifdef _LIBC +# include +# else +# include "gettext.h" +# endif +# ifndef _ +# define _(msgid) gettext (msgid) +# endif -# ifdef _LIBC -# include -# endif +# ifdef _LIBC +# include +# endif static _Noreturn void print_and_abort (void) @@ -342,11 +337,11 @@ print_and_abort (void) happen because the "memory exhausted" message appears in other places like this and the translation should be reused instead of creating a very similar string which requires a separate translation. */ -# ifdef _LIBC +# ifdef _LIBC (void) __fxprintf (NULL, "%s\n", _("memory exhausted")); -# else +# else fprintf (stderr, "%s\n", _("memory exhausted")); -# endif +# endif exit (obstack_exit_failure); } @@ -358,14 +353,15 @@ print_and_abort (void) 'print_and_abort'. */ void (*obstack_alloc_failed_handler) (void) = print_and_abort; -# ifdef _LIBC -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +# ifdef _LIBC +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) /* A looong time ago (before 1994, anyway; we're not sure) this global variable was used by non-GNU-C macros to avoid multiple evaluation. The GNU C library still exports it because somebody might use it. */ struct obstack *_obstack_compat = 0; compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); +# endif # endif # endif -#endif /* !ELIDE_CODE */ +#endif /* !__OBSTACK_ELIDE_CODE */ diff --git a/lib/obstack.h b/lib/obstack.h index daf28bd..19a8eb2 100644 --- a/lib/obstack.h +++ b/lib/obstack.h @@ -104,10 +104,69 @@ #ifndef _OBSTACK_H #define _OBSTACK_H 1 +#ifndef __OBSTACK_INTERFACE_VERSION +# define __OBSTACK_INTERFACE_VERSION 2 +#endif + +/* Comment out all the obstack.c code if we are using the GNU C + Library, and are not actually compiling the library itself, and the + installed library supports the same library interface we do. This + code is part of the GNU C Library, but also included in many other + GNU distributions. Compiling and linking in obstack.c code is a + waste when using the GNU C library (especially if it is a shared + library). Rather than having every GNU program understand + 'configure --with-gnu-libc' and omit the object files, it is + simpler to just do this in the source for each such file. */ + +#include /* Random thing to get __GNU_LIBRARY__. */ +#if defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 +# include +# if (!defined _LIBC \ + && (_GNU_OBSTACK_INTERFACE_VERSION >= __OBSTACK_INTERFACE_VERSION \ + || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \ + && __OBSTACK_INTERFACE_VERSION == 2 \ + && defined SIZEOF_INT && defined SIZEOF_SIZE_T \ + && SIZEOF_INT == SIZEOF_SIZE_T))) +# define __OBSTACK_ELIDE_CODE +# endif +# if (defined _LIBC \ + && _GNU_OBSTACK_INTERFACE_VERSION >= 2 \ + && defined SIZEOF_INT && defined SIZEOF_SIZE_T \ + && SIZEOF_INT == SIZEOF_SIZE_T) +/* We are currently building for glibc, and the version 1 code is ABI + compatible with version 2. When building version 2, don't emit any + code. When building version 1, emit aliases for version 2. */ +# if __OBSTACK_INTERFACE_VERSION == 2 +# define __OBSTACK_ELIDE_CODE +# endif +# if __OBSTACK_INTERFACE_VERSION == 1 +# define __OBSTACK_ALIAS_VER2 +# endif +# endif +#endif + #include -#define __OBSTACK_SIZE_T unsigned int -#define __CHUNK_SIZE_T unsigned long +#if __OBSTACK_INTERFACE_VERSION == 1 +/* For binary compatibility with obstack version 1, which used "int" + and "long" for these two types. */ +# define __OBSTACK_SIZE_T unsigned int +# define __CHUNK_SIZE_T unsigned long +#else +/* Version 2 with sane types, especially for 64-bit hosts. */ +# define __OBSTACK_SIZE_T size_t +# define __CHUNK_SIZE_T size_t + +/* The functions in obstack.c are renamed for version 2 so old shared + libraries that want version 1 code won't accidentally be overridden + by obstack functions with an incompatible ABI. */ +# define _obstack_allocated_p _obstack2_allocated_p +# define _obstack_begin _obstack2_begin +# define _obstack_begin_1 _obstack2_begin_1 +# define _obstack_free _obstack2_free +# define _obstack_memory_used _obstack2_memory_used +# define _obstack_newchunk _obstack2_newchunk +#endif /* If B is the base of an object addressed by P, return the result of aligning P to the next multiple of A + 1. B and P must be of type @@ -184,6 +243,17 @@ extern int _obstack_begin_1 (struct obstack *, __OBSTACK_SIZE_T, int, extern __OBSTACK_SIZE_T _obstack_memory_used (struct obstack *) __attribute_pure__; +#ifdef __OBSTACK_ALIAS_VER2 +extern void _obstack2_newchunk (struct obstack *, __OBSTACK_SIZE_T); +extern void _obstack2_free (struct obstack *, void *); +extern int _obstack2_begin (struct obstack *, __OBSTACK_SIZE_T, int, + void *(*)(size_t), void (*)(void *)); +extern int _obstack2_begin_1 (struct obstack *, __OBSTACK_SIZE_T, int, + void *(*)(void *, size_t), + void (*)(void *, void *), void *); +extern __OBSTACK_SIZE_T _obstack2_memory_used (struct obstack *) + __attribute_pure__; +#endif /* Error handler called when 'obstack_chunk_alloc' failed to allocate more memory. This can be set to a user defined function which diff --git a/modules/obstack b/modules/obstack index bceecdc..b2b8382 100644 --- a/modules/obstack +++ b/modules/obstack @@ -14,6 +14,7 @@ stdlib configure.ac: AC_FUNC_OBSTACK dnl Note: AC_FUNC_OBSTACK does AC_LIBSOURCES([obstack.h, obstack.c]). +AC_LIBOBJ([obstack]) Makefile.am: