2005-10-14  Paul Eggert  <eggert@cs.ucla.edu>
	* malloc/obstack.c: Fix old comments.  Update FSF snail mail address.
	* malloc/obstack.h: Likewise.

	[BZ #321]
	Fix portability bugs encountered when porting to Itanium.
	* malloc/obstack.h (obstack_empty_p, obstack_finish): Do not
	assume that the "contents" member is suitably aligned.  It is
	not, for some hosts and alignments: e.g., Itanium, long-double.
	* malloc/obstack.c (_obstack_begin, _obstack_begin_1,
	_obstack_newchunk): Likewise.
	* malloc/obstack.c: Include <stddef.h>, for size_t.
	Include <inttypes.h>, <stdint.h> if needed and available.
	(DEFAULT_ALIGNMENT): Now an enum constant, not a macro.
	Use C89 offsetof rather than K&R trick.
	Use the maximum alignment of uintmax_t, long double, void *
	rather than the alignment of double.
	(union fooround): Use uintmax_t, long double, void * members
	rather than just long and double.

	[BZ #321]
	Fix portability bugs encountered when porting to the IBM iSeries,
	where pointers are 256 bits wide and no integers are that wide.
	* malloc/obstack.h (__PTR_TO_INT, __INT_TO_PTR): Remove.
	All uses changed to:
	(__BPTR_ALIGN, __PTR_ALIGN): New macros.
	(struct _obstack_chunk.temp): Change from int to a union
	of pointer and int.  All uses changed.

	[BZ #321]
	* malloc/obstack.c (print_and_abort) [!_LIBC]:
	Call fprintf (stderr, ...), not __fxprintf (NULL, ...).
	[_LIBC && USE_IN_LIBIO]: Don't include <wchar.h>; no longer needed.
This commit is contained in:
Roland McGrath 2006-01-11 05:43:11 +00:00
parent 49a0ba2748
commit 2fd4de4b15
3 changed files with 140 additions and 66 deletions

View File

@ -1,3 +1,38 @@
2005-10-14 Paul Eggert <eggert@cs.ucla.edu>
* malloc/obstack.c: Fix old comments. Update FSF snail mail address.
* malloc/obstack.h: Likewise.
[BZ #321]
Fix portability bugs encountered when porting to Itanium.
* malloc/obstack.h (obstack_empty_p, obstack_finish): Do not
assume that the "contents" member is suitably aligned. It is
not, for some hosts and alignments: e.g., Itanium, long-double.
* malloc/obstack.c (_obstack_begin, _obstack_begin_1,
_obstack_newchunk): Likewise.
* malloc/obstack.c: Include <stddef.h>, for size_t.
Include <inttypes.h>, <stdint.h> if needed and available.
(DEFAULT_ALIGNMENT): Now an enum constant, not a macro.
Use C89 offsetof rather than K&R trick.
Use the maximum alignment of uintmax_t, long double, void *
rather than the alignment of double.
(union fooround): Use uintmax_t, long double, void * members
rather than just long and double.
[BZ #321]
Fix portability bugs encountered when porting to the IBM iSeries,
where pointers are 256 bits wide and no integers are that wide.
* malloc/obstack.h (__PTR_TO_INT, __INT_TO_PTR): Remove.
All uses changed to:
(__BPTR_ALIGN, __PTR_ALIGN): New macros.
(struct _obstack_chunk.temp): Change from int to a union
of pointer and int. All uses changed.
[BZ #321]
* malloc/obstack.c (print_and_abort) [!_LIBC]:
Call fprintf (stderr, ...), not __fxprintf (NULL, ...).
[_LIBC && USE_IN_LIBIO]: Don't include <wchar.h>; no longer needed.
2006-01-10 Derek Price <derek@ximbiot.com>
Paul Eggert <eggert@cs.ucla.edu>

View File

@ -1,8 +1,7 @@
/* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1996, 1997, 1998,
1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of the GNU C Library. Its master source is NOT part of
the C library, however. The master source lives in /gd/gnu/lib.
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
@ -16,8 +15,9 @@
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. */
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
#ifdef HAVE_CONFIG_H
# include <config.h>
@ -52,22 +52,38 @@
# endif
#endif
#if defined _LIBC && defined USE_IN_LIBIO
# include <wchar.h>
#endif
#include <stddef.h>
#ifndef ELIDE_CODE
# if HAVE_INTTYPES_H
# include <inttypes.h>
# endif
# if HAVE_STDINT_H || defined _LIBC
# include <stdint.h>
# endif
/* Determine default alignment. */
struct fooalign {char x; double d;};
# define DEFAULT_ALIGNMENT \
((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
union fooround
{
uintmax_t i;
long double d;
void *p;
};
struct fooalign
{
char c;
union fooround u;
};
/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
But in fact it might be less smart and round addresses to as much as
DEFAULT_ROUNDING. So we prepare for it to do that. */
union fooround {long x; double d;};
# define DEFAULT_ROUNDING (sizeof (union fooround))
enum
{
DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
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;
@ -143,7 +159,7 @@ _obstack_begin (struct obstack *h,
register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
alignment = (int) DEFAULT_ALIGNMENT;
alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@ -170,7 +186,8 @@ _obstack_begin (struct obstack *h,
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
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;
@ -189,7 +206,7 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
register struct _obstack_chunk *chunk; /* points to new chunk */
if (alignment == 0)
alignment = (int) DEFAULT_ALIGNMENT;
alignment = DEFAULT_ALIGNMENT;
if (size == 0)
/* Default size is what GNU malloc can fit in a 4096-byte block. */
{
@ -217,7 +234,8 @@ _obstack_begin_1 (struct obstack *h, int size, int alignment,
chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
if (!chunk)
(*obstack_alloc_failed_handler) ();
h->next_free = h->object_base = chunk->contents;
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;
@ -259,8 +277,7 @@ _obstack_newchunk (struct obstack *h, int length)
/* Compute an aligned object_base in the new chunk */
object_base =
__INT_TO_PTR ((__PTR_TO_INT (new_chunk->contents) + h->alignment_mask)
& ~ (h->alignment_mask));
__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
@ -285,7 +302,10 @@ _obstack_newchunk (struct obstack *h, int length)
/* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain.
But not if that chunk might contain an empty object. */
if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
if (! h->maybe_empty_object
&& (h->object_base
== __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
h->alignment_mask)))
{
new_chunk->prev = old_chunk->prev;
CALL_FREEFUN (h, old_chunk);
@ -410,7 +430,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
(void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
# else
fprintf (stderr, "%s\n", _("memory exhausted"));
# endif
exit (obstack_exit_failure);
}

View File

@ -1,8 +1,7 @@
/* obstack.h - object stack macros
Copyright (C) 1988-1994,1996-1999,2003,2004,2005
Free Software Foundation, Inc.
This file is part of the GNU C Library. Its master source is NOT part of
the C library, however. The master source lives in /gd/gnu/lib.
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
@ -16,8 +15,8 @@
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. */
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA. */
/* Summary:
@ -111,19 +110,7 @@ Summary:
extern "C" {
#endif
/* We use subtraction of (char *) 0 instead of casting to int
because on word-addressable machines a simple cast to int
may ignore the byte-within-word field of the pointer. */
#ifndef __PTR_TO_INT
# define __PTR_TO_INT(P) ((P) - (char *) 0)
#endif
#ifndef __INT_TO_PTR
# define __INT_TO_PTR(P) ((P) + (char *) 0)
#endif
/* We need the type of the resulting object. If __PTRDIFF_TYPE__ is
/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
defined, as with GNU C, use that; that way we don't pollute the
namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
and use ptrdiff_t. */
@ -135,6 +122,23 @@ extern "C" {
# define PTR_INT_TYPE ptrdiff_t
#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
char *. A + 1 must be a power of 2. */
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
/* Similiar 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
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, \
P, A)
#include <string.h>
struct _obstack_chunk /* Lives at front of each chunk. */
@ -151,7 +155,11 @@ struct obstack /* control current object in current 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 */
PTR_INT_TYPE temp; /* Temporary for some macros. */
union
{
PTR_INT_TYPE tempint;
void *tempptr;
} 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,
@ -276,7 +284,10 @@ __extension__ \
# define obstack_empty_p(OBSTACK) \
__extension__ \
({ struct obstack const *__o = (OBSTACK); \
(__o->chunk->prev == 0 && __o->next_free - __o->chunk->contents == 0); })
(__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__ \
@ -375,8 +386,8 @@ __extension__ \
if (__o1->next_free == __value) \
__o1->maybe_empty_object = 1; \
__o1->next_free \
= __INT_TO_PTR ((__PTR_TO_INT (__o1->next_free)+__o1->alignment_mask)\
& ~ (__o1->alignment_mask)); \
= __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; \
@ -400,7 +411,10 @@ __extension__ \
(unsigned) ((h)->chunk_limit - (h)->next_free)
# define obstack_empty_p(h) \
((h)->chunk->prev == 0 && (h)->next_free - (h)->chunk->contents == 0)
((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)
so that we can avoid having void expressions
@ -409,23 +423,23 @@ __extension__ \
but some compilers won't accept it. */
# define obstack_make_room(h,length) \
( (h)->temp = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0))
( (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 = (length), \
(((h)->next_free + (h)->temp > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp), \
(h)->next_free += (h)->temp)
( (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 = (length), \
(((h)->next_free + (h)->temp + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp + 1), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp), \
(h)->next_free += (h)->temp, \
( (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, \
*((h)->next_free)++ = 0)
# define obstack_1grow(h,datum) \
@ -450,10 +464,10 @@ __extension__ \
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
# define obstack_blank(h,length) \
( (h)->temp = (length), \
(((h)->chunk_limit - (h)->next_free < (h)->temp) \
? (_obstack_newchunk ((h), (h)->temp), 0) : 0), \
obstack_blank_fast (h, (h)->temp))
( (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_alloc(h,length) \
(obstack_blank ((h), (length)), obstack_finish ((h)))
@ -468,22 +482,23 @@ __extension__ \
( ((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \
: 0), \
(h)->temp = __PTR_TO_INT ((h)->object_base), \
(h)->temp.tempptr = (h)->object_base, \
(h)->next_free \
= __INT_TO_PTR ((__PTR_TO_INT ((h)->next_free)+(h)->alignment_mask) \
& ~ ((h)->alignment_mask)), \
= __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, \
(void *) __INT_TO_PTR ((h)->temp))
(h)->temp.tempptr)
# define obstack_free(h,obj) \
( (h)->temp = (char *) (obj) - (char *) (h)->chunk, \
(((h)->temp > 0 && (h)->temp < (h)->chunk_limit - (char *) (h)->chunk)\
( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
((((h)->temp.tempint > 0 \
&& (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
? (int) ((h)->next_free = (h)->object_base \
= (h)->temp + (char *) (h)->chunk) \
: (((obstack_free) ((h), (h)->temp + (char *) (h)->chunk), 0), 0)))
= (h)->temp.tempint + (char *) (h)->chunk) \
: (((obstack_free) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0), 0)))
#endif /* not __GNUC__ or not __STDC__ */