64-bit obstack support
diff mbox

Message ID 20140716080412.GB8039@bubble.grove.modra.org
State New
Headers show

Commit Message

Alan Modra July 16, 2014, 8:04 a.m. UTC
In https://sourceware.org/ml/binutils/2014-07/msg00137.html, I bumped
OBSTACK_INTERFACE_VERSION, thinking that with an int -> size_t change
on some function parameters we obviously have an ABI change.

However, it seems that the bump is not really necessary due to the
following:

- the existing obstack support only works for obstacks sized up to
  INTMAX, so we only need to be compatible if passing a size_t in the
  positive int range.
- on 32-bit targets supported by glibc, sizeof(int) == sizeof(size_t),
  so for those targets the change is just substituting an unsigned
  parameter for one that was signed.
- on 64-bit targets supported by glibc, a size_t parameter (at least
  for the first or second parameter) or return from a function, is
  passed in the same register as an int.  I checked aarch64, alpha,
  mips64, powerpc64, s390x, sh64, sparc64, tilegx, x64_64.

That leaves non-glibc supported targets to consider, but I wonder if
they are worth worrying about..  I expect that most modern 64-bit
targets would prove to be similar in that int and size_t are passed to
functions in registers.

Note that in contrast to my previous patch, this one does not make
obstack.chunk_size a size_t, over concern that x86_64-mingw would see
an ABI change if I did that.

Comments?  (Maybe at the Cauldron, I'm about to catch a plane!)

	PR gdb/17133
	* malloc/obstack.h: Formatting.  Test HAVE_STRING_H.
	(__PTR_INT_TYPE): Rename from PTR_INT_TYPE.
	(__attribute_pure__): Define without reference to glibc macro.
	(__extension__): Avoid warning when __GNUC_MINOR__ undefined.
	(struct obstack): Make chunk_size unsigned long, and temp union
	with size_t.  Correct chunkfun prototype to take a size_t.
	(_obstack_newchunk): Update prototype.
	(_obstack_begin, _obstack_begin_1, _obstack_memory_used): Likewise.
	(__obstack_free): Define as _obstack_free.
	(obstack_init, obstack_begin, obstack_specify_allocation_with_arg,
	obstack_chunkfun): Update alloc function casts, formatting.
	For __STDC__ versions of the following macros:
	(obstack_object_size): Return size_t.
	(obstack_room): Likewise, and rename __o.
	(obstack_make_room): Make __len size_t, and use obstack_room.
	(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
	obstack_int_grow, obstack_blank): Likewise.
	(obstack_finish): Use unsigned comparison when comparing aligned
	next_free against chunk_limit.
	(obstack_free): Cast OBJ to remove possible const qualifier.
	Don't wrap __obstack_free in parentheses.
	For !__STDC__ versions of the following macros:
	(obstack_object_size, obstack_room): Return size_t.
	(obstack_make_room): Use temp.i and obstack_room.
	(obstack_grow, obstack_grow0, obstack_1grow, obstack_ptr_grow,
	obstack_int_grow, obstack_blank): Likewise.
	(obstack_finish): Use temp.p.  Use unsigned comparision when
	comparing aligned next_free against chunk_limit.
	(obstack_free): Use temp.p and same comparisons as __STDC__ version.
	Don't wrap __obstack_free in parentheses.
	* malloc/obstack.c: Test HAVE_CONFIG_H.  Include gnu-versions.h.
	(COPYING_UNIT): Delete.
	(_Noreturn): Don't rely on this being defined, define ..
	(__attribute_noreturn__): ..and use this instead.
	(CALL_CHUNKFUN): Update chunkfun cast.
	(chunkfun_t, freefun_t): New typdefs.
	(_obstack_begin_worker): Split out from ..
	(_obstack_begin, _obstack_begin_1): ..here.  Make "size" param
	unsigned long, and correct chunkfun prototype.
	(_obstack_newchunk): Make "length" param size_t and local
	vars size_t.  Use memcpy to move existing object.
	(obstack_free): Update alias.
	(_obstack_memory_used): Return and use size_t local.

Comments

Richard Henderson July 16, 2014, 3:04 p.m. UTC | #1
On 07/16/2014 01:04 AM, Alan Modra wrote:
> - on 64-bit targets supported by glibc, a size_t parameter (at least
>   for the first or second parameter) or return from a function, is
>   passed in the same register as an int.  I checked aarch64, alpha,
>   mips64, powerpc64, s390x, sh64, sparc64, tilegx, x64_64.

It really depends on how the 64-bit target passes 32-bit values.

For alpha and mips64, 32-bit values are always sign-extended.  For ppc64 and
s390x, 32-bit values are extended according to the sign of the type.  These
targets are thus in the same boat as 32-bit targets, where we're safe unless
the values are large.

But some 64-bit targets allow garbage in the high bits when passing a 32-bit
parameter.  I believe this applies to aarch64, sparc64, ia64 and x86_64.  (It
won't be visible often for aarch64 and x86_64, because of how 32-bit operations
zero the high bits, but it can happen.)

For this later set of targets, it's not safe nor abi compatible to widen an int
parameter to size_t.


r~
Joseph Myers July 16, 2014, 9:40 p.m. UTC | #2
On Wed, 16 Jul 2014, Alan Modra wrote:

> In https://sourceware.org/ml/binutils/2014-07/msg00137.html, I bumped
> OBSTACK_INTERFACE_VERSION, thinking that with an int -> size_t change
> on some function parameters we obviously have an ABI change.
> 
> However, it seems that the bump is not really necessary due to the
> following:
> 
> - the existing obstack support only works for obstacks sized up to
>   INTMAX, so we only need to be compatible if passing a size_t in the
>   positive int range.
> - on 32-bit targets supported by glibc, sizeof(int) == sizeof(size_t),
>   so for those targets the change is just substituting an unsigned
>   parameter for one that was signed.
> - on 64-bit targets supported by glibc, a size_t parameter (at least
>   for the first or second parameter) or return from a function, is
>   passed in the same register as an int.  I checked aarch64, alpha,
>   mips64, powerpc64, s390x, sh64, sparc64, tilegx, x64_64.

I don't know about OBSTACK_INTERFACE_VERSION, but for functions exported 
from shared glibc you are likely to need new symbol versions for such a 
change.

* If the upper bits of an int parameter are undefined by the ABI, 
obviously you need new symbol versions and the compat versions of the 
functions need to clear those bits before calling the new versions.

* Even if the upper bits are defined by sign-extension, and passing a 
negative value to the function meant undefined behavior, you still need 
new symbol versions so that a binary built with the new glibc, and passing 
size_t values outside the range of int, will not try to pass those 
out-of-range values to an old libc where the parameters have type int, but 
will fail immediately when run with old glibc.  (This sort of issue is why 
<fenv.h> functions got new versions when the return types changed from 
void to int, for example - you can alias the compat version to the new 
version, but do still need the new symbol version.)

* Much the same applies to return types; in that case, the compat symbol 
must ensure that old binaries always get return values within the range of 
the type they expect to be returned.

> 	PR gdb/17133

It looks like

	[BZ #14483]

may be appropriate here.

> 	(_Noreturn): Don't rely on this being defined, define ..
> 	(__attribute_noreturn__): ..and use this instead.

Various changes such as this appear to be effectively reverting parts of 
the recent sync with gnulib.  Don't do that; if there are problems with 
the portability code, work with gnulib on fixing them.  Also, don't mix 
any formatting changes to otherwise unmodified code into the substantive 
patch.  That is,

* substantive changes to use size_t here;

* any necessary changes to the portability code;

* any fixes to formatting

should each be in separate patches, and in the portability case you should 
get agreement from gnulib as that's the primary user of the portability 
code, which is not of direct concern to glibc otherwise.
Alan Modra July 24, 2014, 6:40 a.m. UTC | #3
On Wed, Jul 16, 2014 at 08:04:03AM -0700, Richard Henderson wrote:
> On 07/16/2014 01:04 AM, Alan Modra wrote:
> > - on 64-bit targets supported by glibc, a size_t parameter (at least
> >   for the first or second parameter) or return from a function, is
> >   passed in the same register as an int.  I checked aarch64, alpha,
> >   mips64, powerpc64, s390x, sh64, sparc64, tilegx, x64_64.
> 
> It really depends on how the 64-bit target passes 32-bit values.
> 
> For alpha and mips64, 32-bit values are always sign-extended.  For ppc64 and
> s390x, 32-bit values are extended according to the sign of the type.  These
> targets are thus in the same boat as 32-bit targets, where we're safe unless
> the values are large.
> 
> But some 64-bit targets allow garbage in the high bits when passing a 32-bit
> parameter.  I believe this applies to aarch64, sparc64, ia64 and x86_64.  (It
> won't be visible often for aarch64 and x86_64, because of how 32-bit operations
> zero the high bits, but it can happen.)
> 
> For this later set of targets, it's not safe nor abi compatible to widen an int
> parameter to size_t.

Huh, you're correct.  I was focusing more on the case where a binary
compiled using a new obstack.h was dynamically linking an old libc,
but the other case of an old binary dynamically linked to a new libc
is a problem if the high bits can be garbage.  They weren't with the
simple testcase I used (constant value and compiled with mainline
gcc), but that doesn't prove anything..

Thanks!  And thanks to Joseph for pointing me at gnulib.

Patch
diff mbox

diff --git a/malloc/obstack.h b/malloc/obstack.h
index 59ae6e5..be64816 100644
--- a/malloc/obstack.h
+++ b/malloc/obstack.h
@@ -96,7 +96,7 @@ 
 	Because of the way we do it, you can "unwind" an obstack
 	  back to a previous state. (You may remove objects much
 	  as you would with a stack.)
- */
+*/
 
 
 /* Don't do the contents of this file more than once.  */
@@ -110,10 +110,10 @@ 
    and use ptrdiff_t.  */
 
 #ifdef __PTRDIFF_TYPE__
-# define PTR_INT_TYPE __PTRDIFF_TYPE__
+# define __PTR_INT_TYPE __PTRDIFF_TYPE__
 #else
 # include <stddef.h>
-# define PTR_INT_TYPE ptrdiff_t
+# define __PTR_INT_TYPE ptrdiff_t
 #endif
 
 /* If B is the base of an object addressed by P, return the result of
@@ -122,77 +122,88 @@ 
 
 #define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
 
-/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
+/* Similar to __BPTR_ALIGN (B, P, A), except optimize the common case
    where pointers can be converted to integers, aligned as integers,
-   and converted back again.  If PTR_INT_TYPE is narrower than a
+   and converted back again.  If __PTR_INT_TYPE is narrower than a
    pointer (e.g., the AS/400), play it safe and compute the alignment
    relative to B.  Otherwise, use the faster strategy of computing the
    alignment relative to 0.  */
 
 #define __PTR_ALIGN(B, P, A)						      \
-  __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
+  __BPTR_ALIGN (sizeof (__PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
 		P, A)
 
-#include <string.h>
+#if defined _LIBC || defined HAVE_STRING_H
+# include <string.h>
+#endif
 
+/* Attribute 'pure' was valid as of gcc 3.0.  */
 #ifndef __attribute_pure__
-# define __attribute_pure__ _GL_ATTRIBUTE_PURE
+# if defined __GNUC__ && __GNUC__ >= 3
+#  define __attribute_pure__ __attribute__ ((__pure__))
+# else
+#  define __attribute_pure__
+# endif
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-struct _obstack_chunk           /* Lives at front of each chunk. */
+struct _obstack_chunk		/* Lives at front of each chunk. */
 {
-  char *limit;                  /* 1 past end of this chunk */
-  struct _obstack_chunk *prev;  /* address of prior chunk or NULL */
-  char contents[4];             /* objects begin here */
+  char *limit;			/* 1 past end of this chunk */
+  struct _obstack_chunk *prev;	/* address of prior chunk or NULL */
+  char contents[4];		/* objects begin here */
 };
 
-struct obstack          /* control current object in current chunk */
+struct obstack		/* control current object in current chunk */
 {
-  long chunk_size;              /* preferred size to allocate chunks in */
-  struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
-  char *object_base;            /* address of object we are building */
-  char *next_free;              /* where to add next char to current object */
-  char *chunk_limit;            /* address of char after current chunk */
+  unsigned long chunk_size;	/* Initial chunk size.  Should be a size_t,
+				   along with the 2nd. arg of obstack_begin*,
+				   but we can't change without bumping the ABI.
+				   Some targets, eg. x64_64-mingw, have a
+				   32-bit long and 64-bit size_t.  */
+  struct _obstack_chunk *chunk;	/* address of current struct obstack_chunk */
+  char *object_base;		/* address of object we are building */
+  char *next_free;		/* where to add next char to current object */
+  char *chunk_limit;		/* address of char after current chunk */
   union
   {
-    PTR_INT_TYPE tempint;
-    void *tempptr;
-  } temp;                       /* Temporary for some macros.  */
-  int alignment_mask;           /* Mask of alignment for each object. */
+    size_t i;
+    void *p;
+  } temp;			/* Temporary for some macros.  */
+  int alignment_mask;		/* Mask of alignment for each object. */
   /* These prototypes vary based on 'use_extra_arg', and we use
      casts to the prototypeless function type in all assignments,
      but having prototypes here quiets -Wstrict-prototypes.  */
-  struct _obstack_chunk *(*chunkfun) (void *, long);
+  struct _obstack_chunk *(*chunkfun) (void *, size_t);
   void (*freefun) (void *, struct _obstack_chunk *);
-  void *extra_arg;              /* first arg for chunk alloc/dealloc funcs */
-  unsigned use_extra_arg : 1;     /* chunk alloc/dealloc funcs take extra arg */
+  void *extra_arg;		/* first arg for chunk alloc/dealloc funcs */
+  unsigned use_extra_arg : 1;	  /* chunk alloc/dealloc funcs take extra arg */
   unsigned maybe_empty_object : 1; /* There is a possibility that the current
 				      chunk contains a zero-length object.  This
 				      prevents freeing the chunk if we allocate
 				      a bigger chunk to replace it. */
-  unsigned alloc_failed : 1;      /* No longer used, as we now call the failed
+  unsigned alloc_failed : 1;	  /* No longer used, as we now call the failed
 				     handler on error, but retained for binary
 				     compatibility.  */
 };
 
 /* Declare the external functions we use; they are in obstack.c.  */
 
-extern void _obstack_newchunk (struct obstack *, int);
-extern int _obstack_begin (struct obstack *, int, int,
-			   void *(*)(long), void (*)(void *));
-extern int _obstack_begin_1 (struct obstack *, int, int,
-			     void *(*)(void *, long),
-			     void (*)(void *, void *), void *);
-extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
+extern void _obstack_newchunk (struct obstack *, size_t);
+extern int _obstack_begin (struct obstack *, unsigned long, int,
+			   void *(*) (size_t), void (*) (void *));
+extern int _obstack_begin_1 (struct obstack *, unsigned long, int,
+			     void *(*) (void *, size_t),
+			     void (*) (void *, void *), void *);
+extern size_t _obstack_memory_used (struct obstack *) __attribute_pure__;
 
-/* The default name of the function for freeing a chunk is 'obstack_free',
+/* The default name of the function for freeing a chunk is '_obstack_free',
    but gnulib users can override this by defining '__obstack_free'.  */
 #ifndef __obstack_free
-# define __obstack_free obstack_free
+# define __obstack_free _obstack_free
 #endif
 extern void __obstack_free (struct obstack *, void *);
 
@@ -218,38 +229,38 @@  extern int obstack_exit_failure;
 
 /* Pointer to next byte not yet allocated in current chunk.  */
 
-#define obstack_next_free(h)    ((h)->next_free)
+#define obstack_next_free(h) ((h)->next_free)
 
 /* Mask specifying low bits that should be clear in address of an object.  */
 
 #define obstack_alignment_mask(h) ((h)->alignment_mask)
 
 /* To prevent prototype warnings provide complete argument list.  */
-#define obstack_init(h)							      \
-  _obstack_begin ((h), 0, 0,						      \
-		  (void *(*)(long))obstack_chunk_alloc,			      \
-		  (void (*)(void *))obstack_chunk_free)
+#define obstack_init(h)							\
+  _obstack_begin ((h), 0, 0,						\
+		  (void *(*) (size_t)) obstack_chunk_alloc,		\
+		  (void (*) (void *)) obstack_chunk_free)
 
-#define obstack_begin(h, size)						      \
-  _obstack_begin ((h), (size), 0,					      \
-		  (void *(*)(long))obstack_chunk_alloc,			      \
-		  (void (*)(void *))obstack_chunk_free)
+#define obstack_begin(h, size)						\
+  _obstack_begin ((h), (size), 0,					\
+		  (void *(*) (size_t)) obstack_chunk_alloc,		\
+		  (void (*) (void *)) obstack_chunk_free)
 
-#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun)  \
-  _obstack_begin ((h), (size), (alignment),				      \
-		  (void *(*)(long))(chunkfun),				      \
-		  (void (*)(void *))(freefun))
+#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
+  _obstack_begin ((h), (size), (alignment),				\
+		  (void *(*) (size_t)) (chunkfun),			\
+		  (void (*) (void *)) (freefun))
 
 #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
-  _obstack_begin_1 ((h), (size), (alignment),				      \
-		    (void *(*)(void *, long))(chunkfun),		      \
-		    (void (*)(void *, void *))(freefun), (arg))
+  _obstack_begin_1 ((h), (size), (alignment),				\
+		    (void *(*) (void *, size_t)) (chunkfun),		\
+		    (void (*) (void *, void *)) (freefun), (arg))
 
 #define obstack_chunkfun(h, newchunkfun) \
-  ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
+  ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, size_t)) (newchunkfun))
 
 #define obstack_freefun(h, newfreefun) \
-  ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
+  ((h)->freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun))
 
 #define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
 
@@ -258,7 +269,7 @@  extern int obstack_exit_failure;
 #define obstack_memory_used(h) _obstack_memory_used (h)
 
 #if defined __GNUC__
-# if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
+# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008
 #  define __extension__
 # endif
 
@@ -267,159 +278,160 @@  extern int obstack_exit_failure;
    without using a global variable.
    Also, we can avoid using the 'temp' slot, to make faster code.  */
 
-# define obstack_object_size(OBSTACK)					      \
-  __extension__								      \
-    ({ struct obstack const *__o = (OBSTACK);				      \
-       (unsigned) (__o->next_free - __o->object_base); })
-
-# define obstack_room(OBSTACK)						      \
-  __extension__								      \
-    ({ struct obstack const *__o = (OBSTACK);				      \
-       (unsigned) (__o->chunk_limit - __o->next_free); })
-
-# define obstack_make_room(OBSTACK, length)				      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       int __len = (length);						      \
-       if (__o->chunk_limit - __o->next_free < __len)			      \
-	 _obstack_newchunk (__o, __len);				      \
-       (void) 0; })
-
-# define obstack_empty_p(OBSTACK)					      \
-  __extension__								      \
-    ({ struct obstack const *__o = (OBSTACK);				      \
-       (__o->chunk->prev == 0						      \
-	&& __o->next_free == __PTR_ALIGN ((char *) __o->chunk,		      \
-					  __o->chunk->contents,		      \
-					  __o->alignment_mask)); })
-
-# define obstack_grow(OBSTACK, where, length)				      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       int __len = (length);						      \
-       if (__o->next_free + __len > __o->chunk_limit)			      \
-	 _obstack_newchunk (__o, __len);				      \
-       memcpy (__o->next_free, where, __len);				      \
-       __o->next_free += __len;						      \
-       (void) 0; })
-
-# define obstack_grow0(OBSTACK, where, length)				      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       int __len = (length);						      \
-       if (__o->next_free + __len + 1 > __o->chunk_limit)		      \
-	 _obstack_newchunk (__o, __len + 1);				      \
-       memcpy (__o->next_free, where, __len);				      \
-       __o->next_free += __len;						      \
-       *(__o->next_free)++ = 0;						      \
-       (void) 0; })
-
-# define obstack_1grow(OBSTACK, datum)					      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       if (__o->next_free + 1 > __o->chunk_limit)			      \
-	 _obstack_newchunk (__o, 1);					      \
-       obstack_1grow_fast (__o, datum);					      \
-       (void) 0; })
+# define obstack_object_size(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack const *__o = (OBSTACK);				\
+     (size_t) (__o->next_free - __o->object_base); })
+
+/* The local variable is named __o1 to avoid a shadowed variable
+   warning when invoked from other obstack macros.  */
+# define obstack_room(OBSTACK)						\
+  __extension__								\
+  ({ struct obstack const *__o1 = (OBSTACK);				\
+     (size_t) (__o1->chunk_limit - __o1->next_free); })
+
+# define obstack_make_room(OBSTACK, length)				\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     size_t __len = (length);						\
+     if (obstack_room (__o) < __len)					\
+       _obstack_newchunk (__o, __len);					\
+     (void) 0; })
+
+# define obstack_empty_p(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack const *__o = (OBSTACK);				\
+     (__o->chunk->prev == 0						\
+      && __o->next_free == __PTR_ALIGN ((char *) __o->chunk,		\
+					__o->chunk->contents,		\
+					__o->alignment_mask)); })
+
+# define obstack_grow(OBSTACK, where, length)				\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     size_t __len = (length);						\
+     if (obstack_room (__o) < __len)					\
+       _obstack_newchunk (__o, __len);					\
+     memcpy (__o->next_free, where, __len);				\
+     __o->next_free += __len;						\
+     (void) 0; })
+
+# define obstack_grow0(OBSTACK, where, length)				\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     size_t __len = (length);						\
+     if (obstack_room (__o) < __len + 1)				\
+       _obstack_newchunk (__o, __len + 1);				\
+     memcpy (__o->next_free, where, __len);				\
+     __o->next_free += __len;						\
+     *(__o->next_free)++ = 0;						\
+     (void) 0; })
+
+# define obstack_1grow(OBSTACK, datum)					\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     if (obstack_room (__o) < 1)					\
+       _obstack_newchunk (__o, 1);					\
+     obstack_1grow_fast (__o, datum);					\
+     (void) 0; })
 
 /* These assume that the obstack alignment is good enough for pointers
    or ints, and that the data added so far to the current object
    shares that much alignment.  */
 
-# define obstack_ptr_grow(OBSTACK, datum)				      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       if (__o->next_free + sizeof (void *) > __o->chunk_limit)		      \
-	 _obstack_newchunk (__o, sizeof (void *));			      \
-       obstack_ptr_grow_fast (__o, datum); })				      \
-
-# define obstack_int_grow(OBSTACK, datum)				      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       if (__o->next_free + sizeof (int) > __o->chunk_limit)		      \
-	 _obstack_newchunk (__o, sizeof (int));				      \
-       obstack_int_grow_fast (__o, datum); })
-
-# define obstack_ptr_grow_fast(OBSTACK, aptr)				      \
-  __extension__								      \
-    ({ struct obstack *__o1 = (OBSTACK);				      \
-       void *__p1 = __o1->next_free;					      \
-       *(const void **) __p1 = (aptr);					      \
-       __o1->next_free += sizeof (const void *);			      \
-       (void) 0; })
-
-# define obstack_int_grow_fast(OBSTACK, aint)				      \
-  __extension__								      \
-    ({ struct obstack *__o1 = (OBSTACK);				      \
-       void *__p1 = __o1->next_free;					      \
-       *(int *) __p1 = (aint);						      \
-       __o1->next_free += sizeof (int);					      \
-       (void) 0; })
-
-# define obstack_blank(OBSTACK, length)					      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       int __len = (length);						      \
-       if (__o->chunk_limit - __o->next_free < __len)			      \
-	 _obstack_newchunk (__o, __len);				      \
-       obstack_blank_fast (__o, __len);					      \
-       (void) 0; })
-
-# define obstack_alloc(OBSTACK, length)					      \
-  __extension__								      \
-    ({ struct obstack *__h = (OBSTACK);					      \
-       obstack_blank (__h, (length));					      \
-       obstack_finish (__h); })
-
-# define obstack_copy(OBSTACK, where, length)				      \
-  __extension__								      \
-    ({ struct obstack *__h = (OBSTACK);					      \
-       obstack_grow (__h, (where), (length));				      \
-       obstack_finish (__h); })
-
-# define obstack_copy0(OBSTACK, where, length)				      \
-  __extension__								      \
-    ({ struct obstack *__h = (OBSTACK);					      \
-       obstack_grow0 (__h, (where), (length));				      \
-       obstack_finish (__h); })
-
-/* The local variable is named __o1 to avoid a name conflict
-   when obstack_blank is called.  */
-# define obstack_finish(OBSTACK)					      \
-  __extension__								      \
-    ({ struct obstack *__o1 = (OBSTACK);				      \
-       void *__value = (void *) __o1->object_base;			      \
-       if (__o1->next_free == __value)					      \
-	 __o1->maybe_empty_object = 1;					      \
-       __o1->next_free							      \
-	 = __PTR_ALIGN (__o1->object_base, __o1->next_free,		      \
-			__o1->alignment_mask);				      \
-       if (__o1->next_free - (char *) __o1->chunk			      \
-	   > __o1->chunk_limit - (char *) __o1->chunk)			      \
-	 __o1->next_free = __o1->chunk_limit;				      \
-       __o1->object_base = __o1->next_free;				      \
-       __value; })
-
-# define obstack_free(OBSTACK, OBJ)					      \
-  __extension__								      \
-    ({ struct obstack *__o = (OBSTACK);					      \
-       void *__obj = (OBJ);						      \
-       if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit)  \
-	 __o->next_free = __o->object_base = (char *) __obj;		      \
-       else (__obstack_free) (__o, __obj); })
+# define obstack_ptr_grow(OBSTACK, datum)				\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     if (obstack_room (__o) < sizeof (void *))				\
+       _obstack_newchunk (__o, sizeof (void *));			\
+     obstack_ptr_grow_fast (__o, datum); })
+
+# define obstack_int_grow(OBSTACK, datum)				\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     if (obstack_room (__o) < sizeof (int))				\
+       _obstack_newchunk (__o, sizeof (int));				\
+     obstack_int_grow_fast (__o, datum); })
+
+# define obstack_ptr_grow_fast(OBSTACK, aptr)				\
+  __extension__								\
+  ({ struct obstack *__o1 = (OBSTACK);					\
+     void *__p1 = __o1->next_free;					\
+     *(const void **) __p1 = (aptr);					\
+     __o1->next_free += sizeof (const void *);				\
+     (void) 0; })
+
+# define obstack_int_grow_fast(OBSTACK, aint)				\
+  __extension__								\
+  ({ struct obstack *__o1 = (OBSTACK);					\
+     void *__p1 = __o1->next_free;					\
+     *(int *) __p1 = (aint);						\
+     __o1->next_free += sizeof (int);					\
+     (void) 0; })
+
+# define obstack_blank(OBSTACK, length)					\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     size_t __len = (length);						\
+     if (obstack_room (__o) < __len)					\
+       _obstack_newchunk (__o, __len);					\
+     obstack_blank_fast (__o, __len);					\
+     (void) 0; })
+
+# define obstack_alloc(OBSTACK, length)					\
+  __extension__								\
+  ({ struct obstack *__h = (OBSTACK);					\
+     obstack_blank (__h, (length));					\
+     obstack_finish (__h); })
+
+# define obstack_copy(OBSTACK, where, length)				\
+  __extension__								\
+  ({ struct obstack *__h = (OBSTACK);					\
+     obstack_grow (__h, (where), (length));				\
+     obstack_finish (__h); })
+
+# define obstack_copy0(OBSTACK, where, length)				\
+  __extension__								\
+  ({ struct obstack *__h = (OBSTACK);					\
+     obstack_grow0 (__h, (where), (length));				\
+     obstack_finish (__h); })
+
+# define obstack_finish(OBSTACK)					\
+  __extension__								\
+  ({ struct obstack *__o1 = (OBSTACK);					\
+     void *__value = (void *) __o1->object_base;			\
+     if (__o1->next_free == __value)					\
+       __o1->maybe_empty_object = 1;					\
+     __o1->next_free = __PTR_ALIGN (__o1->object_base, __o1->next_free,	\
+				    __o1->alignment_mask);		\
+     if ((size_t) (__o1->next_free - (char *) __o1->chunk)		\
+	 > (size_t) (__o1->chunk_limit - (char *) __o1->chunk))		\
+       __o1->next_free = __o1->chunk_limit;				\
+     __o1->object_base = __o1->next_free;				\
+     __value; })
+
+# define obstack_free(OBSTACK, OBJ)					\
+  __extension__								\
+  ({ struct obstack *__o = (OBSTACK);					\
+     void *__obj = (void *) (OBJ);					\
+     if (__obj > (void *) __o->chunk					\
+	 && __obj < (void *) __o->chunk_limit)				\
+       __o->next_free = __o->object_base = (char *) __obj;		\
+     else								\
+       __obstack_free (__o, __obj); })
 
 #else /* not __GNUC__ */
 
 # define obstack_object_size(h) \
-  (unsigned) ((h)->next_free - (h)->object_base)
+  ((size_t) ((h)->next_free - (h)->object_base))
 
-# define obstack_room(h)						      \
-  (unsigned) ((h)->chunk_limit - (h)->next_free)
+# define obstack_room(h) \
+  ((size_t) ((h)->chunk_limit - (h)->next_free))
 
 # define obstack_empty_p(h) \
-  ((h)->chunk->prev == 0						      \
-   && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk,		      \
-				     (h)->chunk->contents,		      \
+  ((h)->chunk->prev == 0						\
+   && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk,		\
+				     (h)->chunk->contents,		\
 				     (h)->alignment_mask))
 
 /* Note that the call to _obstack_newchunk is enclosed in (..., 0)
@@ -427,89 +439,86 @@  extern int obstack_exit_failure;
    in the arms of the conditional expression.
    Casting the third operand to void was tried before,
    but some compilers won't accept it.  */
-
-# define obstack_make_room(h, length)					      \
-  ((h)->temp.tempint = (length),					      \
-   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		      \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
-
-# define obstack_grow(h, where, length)					      \
-  ((h)->temp.tempint = (length),					      \
-   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		      \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		      \
-   memcpy ((h)->next_free, where, (h)->temp.tempint),			      \
-   (h)->next_free += (h)->temp.tempint)
-
-# define obstack_grow0(h, where, length)				      \
-  ((h)->temp.tempint = (length),					      \
-   (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit)		      \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0),		      \
-   memcpy ((h)->next_free, where, (h)->temp.tempint),			      \
-   (h)->next_free += (h)->temp.tempint,					      \
+# define obstack_make_room(h, length)					\
+  ((h)->temp.i = (length),						\
+   ((obstack_room (h) < (h)->temp.i)					\
+    ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0))
+
+# define obstack_grow(h, where, length)					\
+  ((h)->temp.i = (length),						\
+   ((obstack_room (h) < (h)->temp.i)					\
+    ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0),			\
+   memcpy ((h)->next_free, where, (h)->temp.i),				\
+   (h)->next_free += (h)->temp.i)
+
+# define obstack_grow0(h, where, length)				\
+  ((h)->temp.i = (length),						\
+   ((obstack_room (h) < (h)->temp.i + 1)				\
+    ? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0),		\
+   memcpy ((h)->next_free, where, (h)->temp.i),				\
+   (h)->next_free += (h)->temp.i,					\
    *((h)->next_free)++ = 0)
 
-# define obstack_1grow(h, datum)					      \
-  ((((h)->next_free + 1 > (h)->chunk_limit)				      \
-    ? (_obstack_newchunk ((h), 1), 0) : 0),				      \
+# define obstack_1grow(h, datum)					\
+  (((obstack_room (h) < 1)						\
+    ? (_obstack_newchunk ((h), 1), 0) : 0),				\
    obstack_1grow_fast (h, datum))
 
-# define obstack_ptr_grow(h, datum)					      \
-  ((((h)->next_free + sizeof (char *) > (h)->chunk_limit)		      \
-    ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0),		      \
+# define obstack_ptr_grow(h, datum)					\
+  ((((h)->next_free + sizeof (char *) > (h)->chunk_limit)		\
+    ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0),		\
    obstack_ptr_grow_fast (h, datum))
 
-# define obstack_int_grow(h, datum)					      \
-  ((((h)->next_free + sizeof (int) > (h)->chunk_limit)			      \
-    ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0),			      \
+# define obstack_int_grow(h, datum)					\
+  (((obstack_room (h) < sizeof (int))					\
+    ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0),			\
    obstack_int_grow_fast (h, datum))
 
-# define obstack_ptr_grow_fast(h, aptr)					      \
+# define obstack_ptr_grow_fast(h, aptr)					\
   (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
 
-# define obstack_int_grow_fast(h, aint)					      \
+# define obstack_int_grow_fast(h, aint)					\
   (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
 
-# define obstack_blank(h, length)					      \
-  ((h)->temp.tempint = (length),					      \
-   (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint)		      \
-   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		      \
-   obstack_blank_fast (h, (h)->temp.tempint))
+# define obstack_blank(h, length)					\
+  ((h)->temp.i = (length),						\
+   ((obstack_room (h) < (h)->temp.i)					\
+    ? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0),			\
+   obstack_blank_fast (h, (h)->temp.i))
 
-# define obstack_alloc(h, length)					      \
+# define obstack_alloc(h, length)					\
   (obstack_blank ((h), (length)), obstack_finish ((h)))
 
-# define obstack_copy(h, where, length)					      \
+# define obstack_copy(h, where, length)					\
   (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
 
-# define obstack_copy0(h, where, length)				      \
+# define obstack_copy0(h, where, length)				\
   (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
 
-# define obstack_finish(h)						      \
-  (((h)->next_free == (h)->object_base					      \
-    ? (((h)->maybe_empty_object = 1), 0)				      \
-    : 0),								      \
-   (h)->temp.tempptr = (h)->object_base,				      \
-   (h)->next_free							      \
-     = __PTR_ALIGN ((h)->object_base, (h)->next_free,			      \
-		    (h)->alignment_mask),				      \
-   (((h)->next_free - (char *) (h)->chunk				      \
-     > (h)->chunk_limit - (char *) (h)->chunk)				      \
-   ? ((h)->next_free = (h)->chunk_limit) : 0),				      \
-   (h)->object_base = (h)->next_free,					      \
-   (h)->temp.tempptr)
-
-# define obstack_free(h, obj)						      \
-  ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk,		      \
-   ((((h)->temp.tempint > 0						      \
-      && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk))	      \
-    ? (void) ((h)->next_free = (h)->object_base				      \
-	      = (h)->temp.tempint + (char *) (h)->chunk)		      \
-    : (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
+# define obstack_finish(h)						\
+  (((h)->next_free == (h)->object_base					\
+    ? (((h)->maybe_empty_object = 1), 0)				\
+    : 0),								\
+   (h)->temp.p = (h)->object_base,					\
+   (h)->next_free = __PTR_ALIGN ((h)->object_base, (h)->next_free,	\
+				 (h)->alignment_mask),			\
+   (((size_t) ((h)->next_free - (char *) (h)->chunk)			\
+     > (size_t) ((h)->chunk_limit - (char *) (h)->chunk))		\
+    ? ((h)->next_free = (h)->chunk_limit) : 0),				\
+   (h)->object_base = (h)->next_free,					\
+   (h)->temp.p)
+
+# define obstack_free(h, obj)						\
+  ((h)->temp.p = (void *) (obj),					\
+   (((h)->temp.p > (void *) (h)->chunk					\
+     && (h)->temp.p < (void *) (h)->chunk_limit)			\
+    ? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \
+    : __obstack_free ((h), (h)->temp.p)))
 
 #endif /* not __GNUC__ */
 
 #ifdef __cplusplus
-}       /* C++ */
+}	/* C++ */
 #endif
 
-#endif /* obstack.h */
+#endif /* _OBSTACK_H */
diff --git a/malloc/obstack.c b/malloc/obstack.c
index fa4fefc..1838115 100644
--- a/malloc/obstack.c
+++ b/malloc/obstack.c
@@ -21,7 +21,9 @@ 
 # include <obstack.h>
 # include <shlib-compat.h>
 #else
-# include <config.h>
+# ifdef HAVE_CONFIG_H
+#  include "config.h"
+# endif
 # include "obstack.h"
 #endif
 
@@ -47,11 +49,9 @@ 
 # endif
 #endif
 
-#include <stddef.h>
-
 #ifndef ELIDE_CODE
 
-
+# include <stddef.h>
 # include <stdint.h>
 
 /* Determine default alignment.  */
@@ -75,22 +75,22 @@  enum
   DEFAULT_ROUNDING = sizeof (union fooround)
 };
 
-/* When we copy a long block of data, this is the unit to do it with.
-   On some machines, copying successive ints does not work;
-   in such a case, redefine COPYING_UNIT to 'long' (if that works)
-   or 'char' as a last resort.  */
-# ifndef COPYING_UNIT
-#  define COPYING_UNIT int
-# endif
-
-
 /* The functions allocating more room by calling 'obstack_chunk_alloc'
    jump to the handler pointed to by 'obstack_alloc_failed_handler'.
    This can be set to a user defined function which should either
    abort gracefully or use longjump - but shouldn't return.  This
    variable by default points to the internal function
    'print_and_abort'.  */
-static _Noreturn void print_and_abort (void);
+
+# ifndef __attribute_noreturn__
+#  if (defined __GNUC__ && defined __GNUC_MINOR__			\
+       && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2007)
+#   define __attribute_noreturn__ __attribute__ ((__noreturn__))
+#  else
+#   define __attribute_noreturn__
+#  endif
+# endif
+static void __attribute_noreturn__ print_and_abort (void);
 void (*obstack_alloc_failed_handler) (void) = print_and_abort;
 
 /* Exit value used when 'print_and_abort' is used.  */
@@ -119,17 +119,17 @@  compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
    do not allow (expr) ? void : void.  */
 
 # define CALL_CHUNKFUN(h, size) \
-  (((h)->use_extra_arg)							      \
-   ? (*(h)->chunkfun)((h)->extra_arg, (size))				      \
-   : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
+  (((h)->use_extra_arg)							\
+   ? (*(h)->chunkfun) ((h)->extra_arg, (size))				\
+   : (*(struct _obstack_chunk *(*) (size_t)) (h)->chunkfun) ((size)))
 
 # define CALL_FREEFUN(h, old_chunk) \
-  do { \
-      if ((h)->use_extra_arg)						      \
-	(*(h)->freefun)((h)->extra_arg, (old_chunk));			      \
-      else								      \
-	(*(void (*)(void *))(h)->freefun)((old_chunk));			      \
-    } while (0)
+  do {									\
+    if ((h)->use_extra_arg)						\
+      (*(h)->freefun) ((h)->extra_arg, (old_chunk));			\
+    else								\
+      (*(void (*) (void *)) (h)->freefun) ((old_chunk));		\
+  } while (0)
 
 
 /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
@@ -140,11 +140,14 @@  compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
    Return nonzero if successful, calls obstack_alloc_failed_handler if
    allocation fails.  */
 
-int
-_obstack_begin (struct obstack *h,
-		int size, int alignment,
-		void *(*chunkfun) (long),
-		void (*freefun) (void *))
+typedef struct _obstack_chunk * (*chunkfun_t) (void *, size_t);
+typedef void (*freefun_t) (void *, struct _obstack_chunk *);
+
+static int
+_obstack_begin_worker (struct obstack *h,
+		       unsigned long size, int alignment,
+		       chunkfun_t chunkfun, freefun_t freefun,
+		       void *arg, int use_extra_arg)
 {
   struct _obstack_chunk *chunk; /* points to new chunk */
 
@@ -167,19 +170,19 @@  _obstack_begin (struct obstack *h,
       size = 4096 - extra;
     }
 
-  h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
+  h->chunkfun = chunkfun;
+  h->freefun = freefun;
   h->chunk_size = size;
   h->alignment_mask = alignment - 1;
-  h->use_extra_arg = 0;
+  h->extra_arg = arg;
+  h->use_extra_arg = use_extra_arg;
 
   chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
   if (!chunk)
     (*obstack_alloc_failed_handler) ();
   h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
 					       alignment - 1);
-  h->chunk_limit = chunk->limit
-    = (char *) chunk + h->chunk_size;
+  h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
   chunk->prev = 0;
   /* The initial chunk now contains no empty object.  */
   h->maybe_empty_object = 0;
@@ -188,51 +191,26 @@  _obstack_begin (struct obstack *h,
 }
 
 int
-_obstack_begin_1 (struct obstack *h, int size, int alignment,
-		  void *(*chunkfun) (void *, long),
+_obstack_begin (struct obstack *h,
+		unsigned long size, int alignment,
+		void *(*chunkfun) (size_t),
+		void (*freefun) (void *))
+{
+  return _obstack_begin_worker (h, size, alignment,
+				(chunkfun_t) chunkfun, (freefun_t) freefun,
+				NULL, 0);
+}
+
+int
+_obstack_begin_1 (struct obstack *h,
+		  unsigned long size, int alignment,
+		  void *(*chunkfun) (void *, size_t),
 		  void (*freefun) (void *, void *),
 		  void *arg)
 {
-  struct _obstack_chunk *chunk; /* points to new chunk */
-
-  if (alignment == 0)
-    alignment = DEFAULT_ALIGNMENT;
-  if (size == 0)
-    /* Default size is what GNU malloc can fit in a 4096-byte block.  */
-    {
-      /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
-	 Use the values for range checking, because if range checking is off,
-	 the extra bytes won't be missed terribly, but if range checking is on
-	 and we used a larger request, a whole extra 4096 bytes would be
-	 allocated.
-
-	 These number are irrelevant to the new GNU malloc.  I suspect it is
-	 less sensitive to the size of the request.  */
-      int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
-		    + 4 + DEFAULT_ROUNDING - 1)
-		   & ~(DEFAULT_ROUNDING - 1));
-      size = 4096 - extra;
-    }
-
-  h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
-  h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
-  h->chunk_size = size;
-  h->alignment_mask = alignment - 1;
-  h->extra_arg = arg;
-  h->use_extra_arg = 1;
-
-  chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
-  if (!chunk)
-    (*obstack_alloc_failed_handler) ();
-  h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
-					       alignment - 1);
-  h->chunk_limit = chunk->limit
-    = (char *) chunk + h->chunk_size;
-  chunk->prev = 0;
-  /* The initial chunk now contains no empty object.  */
-  h->maybe_empty_object = 0;
-  h->alloc_failed = 0;
-  return 1;
+  return _obstack_begin_worker (h, size, alignment,
+				(chunkfun_t) chunkfun, (freefun_t) freefun,
+				arg, 1);
 }
 
 /* Allocate a new current chunk for the obstack *H
@@ -242,14 +220,12 @@  _obstack_begin_1 (struct obstack *h, int size, int alignment,
    to the beginning of the new one.  */
 
 void
-_obstack_newchunk (struct obstack *h, int length)
+_obstack_newchunk (struct obstack *h, size_t length)
 {
   struct _obstack_chunk *old_chunk = h->chunk;
   struct _obstack_chunk *new_chunk;
-  long new_size;
-  long obj_size = h->next_free - h->object_base;
-  long i;
-  long already;
+  size_t new_size;
+  size_t obj_size = h->next_free - h->object_base;
   char *object_base;
 
   /* Compute size for new chunk.  */
@@ -260,7 +236,7 @@  _obstack_newchunk (struct obstack *h, int length)
   /* Allocate and initialize the new chunk.  */
   new_chunk = CALL_CHUNKFUN (h, new_size);
   if (!new_chunk)
-    (*obstack_alloc_failed_handler)();
+    (*obstack_alloc_failed_handler) ();
   h->chunk = new_chunk;
   new_chunk->prev = old_chunk;
   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
@@ -269,25 +245,8 @@  _obstack_newchunk (struct obstack *h, int length)
   object_base =
     __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
 
-  /* Move the existing object to the new chunk.
-     Word at a time is fast and is safe if the object
-     is sufficiently aligned.  */
-  if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
-    {
-      for (i = obj_size / sizeof (COPYING_UNIT) - 1;
-	   i >= 0; i--)
-	((COPYING_UNIT *) object_base)[i]
-	  = ((COPYING_UNIT *) h->object_base)[i];
-      /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
-	 but that can cross a page boundary on a machine
-	 which does not do strict alignment for COPYING_UNITS.  */
-      already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
-    }
-  else
-    already = 0;
-  /* Copy remaining bytes one by one.  */
-  for (i = already; i < obj_size; i++)
-    object_base[i] = h->object_base[i];
+  /* Move the existing object to the new chunk.  */
+  memcpy (object_base, h->object_base, obj_size);
 
   /* If the object just copied was the only data in OLD_CHUNK,
      free that chunk and remove it from the chain.
@@ -321,8 +280,8 @@  int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
 int
 _obstack_allocated_p (struct obstack *h, void *obj)
 {
-  struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
-  struct _obstack_chunk *plp;   /* point to previous chunk if any */
+  struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  struct _obstack_chunk *plp;	/* point to previous chunk if any */
 
   lp = (h)->chunk;
   /* We use >= rather than > since the object cannot be exactly at
@@ -344,8 +303,8 @@  _obstack_allocated_p (struct obstack *h, void *obj)
 void
 __obstack_free (struct obstack *h, void *obj)
 {
-  struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
-  struct _obstack_chunk *plp;   /* point to previous chunk if any */
+  struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
+  struct _obstack_chunk *plp;	/* point to previous chunk if any */
 
   lp = h->chunk;
   /* We use >= because there cannot be an object at the beginning of a chunk.
@@ -372,21 +331,19 @@  __obstack_free (struct obstack *h, void *obj)
 }
 
 # ifdef _LIBC
-/* Older versions of libc used a function _obstack_free intended to be
-   called by non-GCC compilers.  */
-strong_alias (obstack_free, _obstack_free)
+/* Older versions of libc declared both _obstack_free and obstack_free.  */
+strong_alias (__obstack_free, obstack_free)
 # endif
 
-int
+size_t
 _obstack_memory_used (struct obstack *h)
 {
   struct _obstack_chunk *lp;
-  int nbytes = 0;
+  size_t nbytes = 0;
 
   for (lp = h->chunk; lp != 0; lp = lp->prev)
-    {
-      nbytes += lp->limit - (char *) lp;
-    }
+    nbytes += lp->limit - (char *) lp;
+
   return nbytes;
 }
 
@@ -404,7 +361,8 @@  _obstack_memory_used (struct obstack *h)
 #  include <libio/iolibio.h>
 # endif
 
-static _Noreturn void
+static void
+__attribute_noreturn__
 print_and_abort (void)
 {
   /* Don't change any of these strings.  Yes, it would be possible to add
@@ -420,4 +378,4 @@  print_and_abort (void)
   exit (obstack_exit_failure);
 }
 
-#endif  /* !ELIDE_CODE */
+#endif	/* !ELIDE_CODE */