diff mbox

[4/5] 64-bit obstack support, part 3

Message ID 1406354233-7664-5-git-send-email-amodra@gmail.com
State Superseded
Headers show

Commit Message

Alan Modra July 26, 2014, 5:57 a.m. UTC
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 mbox

Patch

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 <stdio.h>              /* Random thing to get __GNU_LIBRARY__.  */
-#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
-# include <gnu-versions.h>
-# 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 <stdint.h>
 # include <stdlib.h>
@@ -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 <libintl.h>
-# else
-#  include "gettext.h"
-# endif
-# ifndef _
-#  define _(msgid) gettext (msgid)
-# endif
+#  ifdef _LIBC
+#   include <libintl.h>
+#  else
+#   include "gettext.h"
+#  endif
+#  ifndef _
+#   define _(msgid) gettext (msgid)
+#  endif
 
-# ifdef _LIBC
-#  include <libio/iolibio.h>
-# endif
+#  ifdef _LIBC
+#   include <libio/iolibio.h>
+#  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 <stdio.h>              /* Random thing to get __GNU_LIBRARY__.  */
+#if defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
+# include <gnu-versions.h>
+# 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 <stddef.h>
 
-#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: