From patchwork Wed Oct 29 03:34:53 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 3458 Received: (qmail 5543 invoked by alias); 29 Oct 2014 03:35:08 -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 5529 invoked by uid 89); 29 Oct 2014 03:35:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 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-f170.google.com X-Received: by 10.67.11.42 with SMTP id ef10mr7747345pad.49.1414553701804; Tue, 28 Oct 2014 20:35:01 -0700 (PDT) Date: Wed, 29 Oct 2014 14:04:53 +1030 From: Alan Modra To: libc-alpha@sourceware.org, bug-gnulib@gnu.org Subject: [PATCH] 64-bit obstack support Message-ID: <20141029033453.GO4267@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23 (2014-03-12) And >2G on 32-bit. * include/gnu-versions.h (_GNU_OBSTACK_INTERFACE_VERSION): Bump. * include/obstack.h: Include shlib-compat.h and gnu-versions.h. (_OBSTACK_ELIDE_CODE, _OBSTACK_NO_ERROR_HANDLER, _OBSTACK_COMPAT, _OBSTACK_ALIAS): Define. (_obstack_allocated_p, _obstack_newchunk, _obstack_free, _obstack_begin, _obstack_begin_1, _obstack_memory_used): Define. (_obstack_newchunk): Only use libc_hidden_proto on the version we will use inside glibc. * malloc/obstack.h: Import from gnulib. * malloc/obstack.c: Likewise. * malloc/obstackv1.c: New file. * malloc/obstackv2.c: New file. * malloc/Makefile (routines): Remove obstack. Add obstackv1 and obstackv2. (CFLAGS-obstack.c): Don't define. (CFLAGS-obstackv1.c, CFLAGS-obstackv2.c): Define. (malloc/Versions): Add GLIBC_2.21 _obstack functions. * config.h.in (SIZEOF_INT, SIZEOF_SIZE_T): Add. * configure.in: AC_CHECK_SIZEOF int and size_t. * configure: Regenerate. --- config.h.in | 6 ++ configure | 68 +++++++++++++ configure.ac | 4 + include/gnu-versions.h | 2 +- include/obstack.h | 76 ++++++++++++++ malloc/Makefile | 5 +- malloc/Versions | 4 + malloc/obstack.c | 266 ++++++++++++++++++------------------------------ malloc/obstack.h | 271 +++++++++++++++++++++++++------------------------ malloc/obstackv1.c | 59 +++++++++++ malloc/obstackv2.c | 69 +++++++++++++ 11 files changed, 523 insertions(+), 307 deletions(-) create mode 100644 malloc/obstackv1.c create mode 100644 malloc/obstackv2.c diff --git a/config.h.in b/config.h.in index 20c0825..82cd82b 100644 --- a/config.h.in +++ b/config.h.in @@ -200,6 +200,12 @@ /* Define if the linker defines __ehdr_start. */ #undef HAVE_EHDR_START +/* The size of "int", as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of "size_t", as computed by sizeof. */ +#undef SIZEOF_SIZE_T + /* */ diff --git a/configure.ac b/configure.ac index 82d0896..07b4b0b 100644 --- a/configure.ac +++ b/configure.ac @@ -1799,6 +1799,10 @@ AC_CHECK_SIZEOF(long double, 0) sizeof_long_double=$ac_cv_sizeof_long_double AC_SUBST(sizeof_long_double) +dnl Determine the size of int and size_t for obstack.h. +AC_CHECK_SIZEOF([int]) +AC_CHECK_SIZEOF([size_t],,[#include ]) + CPPUNDEFS= dnl Check for silly hacked compilers predefining _FORTIFY_SOURCE. dnl Since we are building the implementations of the fortified functions here, diff --git a/include/gnu-versions.h b/include/gnu-versions.h index 6ffbd47..99caf5b 100644 --- a/include/gnu-versions.h +++ b/include/gnu-versions.h @@ -43,7 +43,7 @@ remember, if any of these versions change, the libc.so major version number must change too (so avoid it)! */ -#define _GNU_OBSTACK_INTERFACE_VERSION 1 /* vs malloc/obstack.c */ +#define _GNU_OBSTACK_INTERFACE_VERSION 2 /* vs malloc/obstack.c */ #define _GNU_REGEX_INTERFACE_VERSION 1 /* vs posix/regex.c */ #define _GNU_GLOB_INTERFACE_VERSION 1 /* vs posix/glob.c */ #define _GNU_GETOPT_INTERFACE_VERSION 2 /* vs posix/getopt.c and diff --git a/include/obstack.h b/include/obstack.h index 349d59b..b346fba 100644 --- a/include/obstack.h +++ b/include/obstack.h @@ -1,3 +1,79 @@ +/* Control compile of obstackv1.c and obstackv2.c + Copyright (C) 2014 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, see + . */ + +#ifdef _OBSTACK_C +/* We are compiling obstackv1.c or obstackv2.c. */ +# include +# include + +# if _GNU_OBSTACK_INTERFACE_VERSION == 1 +/* Only build version 1 support. */ +# if _OBSTACK_INTERFACE_VERSION != 1 +# define _OBSTACK_ELIDE_CODE +# endif +# elif SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) +# define _OBSTACK_COMPAT +# if (defined SIZEOF_INT && defined SIZEOF_SIZE_T \ + && SIZEOF_INT == SIZEOF_SIZE_T) +/* The version 1 code is ABI compatible with version 2, obstackv1.c is + redundant. When compiling obstackv2.c, emit symbols versioned as + for version 1 obstacks. */ +# if _OBSTACK_INTERFACE_VERSION == 1 +# define _OBSTACK_ELIDE_CODE +# else +# define _OBSTACK_ALIAS +# endif +# else /* SIZEOF_INT != SIZEOF_SIZE_T */ +/* Distinct version 1 and version 2 functions are needed, with the + exception of the error handler. */ +# if _OBSTACK_INTERFACE_VERSION == 1 +# define _OBSTACK_NO_ERROR_HANDLER +# endif +# endif +# else /* !SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) */ +/* We don't want any version 1 support. */ +# if _OBSTACK_INTERFACE_VERSION == 1 +# define _OBSTACK_ELIDE_CODE +# endif +# endif + +# ifdef _OBSTACK_COMPAT +# if _OBSTACK_INTERFACE_VERSION == 1 +# define _obstack_allocated_p _obstackv1_allocated_p +# define _obstack_begin _obstackv1_begin +# define _obstack_begin_1 _obstackv1_begin_1 +# define _obstack_free _obstackv1_free +# define _obstack_memory_used _obstackv1_memory_used +# define _obstack_newchunk _obstackv1_newchunk +# else +# define _obstack_allocated_p _obstackv2_allocated_p +# define _obstack_begin _obstackv2_begin +# define _obstack_begin_1 _obstackv2_begin_1 +# define _obstack_free _obstackv2_free +# define _obstack_memory_used _obstackv2_memory_used +# define _obstack_newchunk _obstackv2_newchunk +# endif +# endif +#endif + #include +#if (!defined _OBSTACK_C \ + || _GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION) libc_hidden_proto (_obstack_newchunk) +#endif diff --git a/malloc/Makefile b/malloc/Makefile index 9e93523..6879d96 100644 --- a/malloc/Makefile +++ b/malloc/Makefile @@ -30,7 +30,7 @@ tests := mallocbug tst-malloc tst-valloc tst-calloc tst-obstack \ tst-pvalloc tst-memalign tst-mallopt test-srcs = tst-mtrace -routines = malloc morecore mcheck mtrace obstack +routines = malloc morecore mcheck mtrace obstackv1 obstackv2 install-lib := libmcheck.a non-lib.a := libmcheck.a @@ -103,7 +103,8 @@ endif include ../Rules CFLAGS-mcheck-init.c = $(PIC-ccflag) -CFLAGS-obstack.c = $(uses-callbacks) +CFLAGS-obstackv1.c = $(uses-callbacks) +CFLAGS-obstackv2.c = $(uses-callbacks) $(objpfx)libmcheck.a: $(objpfx)mcheck-init.o -rm -f $@ diff --git a/malloc/Versions b/malloc/Versions index 7ca9bdf..1c60d21 100644 --- a/malloc/Versions +++ b/malloc/Versions @@ -61,6 +61,10 @@ libc { GLIBC_2.16 { aligned_alloc; } + GLIBC_2.21 { + _obstack_allocated_p; _obstack_begin; _obstack_begin_1; + _obstack_free; _obstack_memory_used; _obstack_newchunk; + } GLIBC_PRIVATE { # Internal startup hook for libpthread. __libc_malloc_pthread_startup; diff --git a/malloc/obstackv1.c b/malloc/obstackv1.c new file mode 100644 index 0000000..24eaee0 --- /dev/null +++ b/malloc/obstackv1.c @@ -0,0 +1,59 @@ +/* obstackv1.c - subroutines used implicitly by object stack macros + Copyright (C) 2014 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, see + . */ + +/* Build version 1 compatibility support. */ +#define _OBSTACK_INTERFACE_VERSION 1 +#define _OBSTACK_C 1 + +#include "obstack.c" + +#ifndef _OBSTACK_ELIDE_CODE + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) +# undef obstack_free +strong_alias (_obstack_free, obstackv1_free) +compat_symbol (libc, obstackv1_free, obstack_free, GLIBC_2_0); +# endif + +# 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 + +# if _GNU_OBSTACK_INTERFACE_VERSION == 1 +libc_hidden_def (_obstack_newchunk) +# endif + +# ifdef _OBSTACK_COMPAT +# undef _obstack_allocated_p +# undef _obstack_begin +# undef _obstack_begin_1 +# undef _obstack_free +# undef _obstack_memory_used +# undef _obstack_newchunk +compat_symbol (libc, _obstackv1_allocated_p, _obstack_allocated_p, GLIBC_2_0); +compat_symbol (libc, _obstackv1_begin, _obstack_begin, GLIBC_2_0); +compat_symbol (libc, _obstackv1_begin_1, _obstack_begin_1, GLIBC_2_0); +compat_symbol (libc, _obstackv1_free, _obstack_free, GLIBC_2_0); +compat_symbol (libc, _obstackv1_memory_used, _obstack_memory_used, GLIBC_2_0); +compat_symbol (libc, _obstackv1_newchunk, _obstack_newchunk, GLIBC_2_0); +# endif /* _OBSTACK_COMPAT */ +#endif /* _OBSTACK_ELIDE_CODE */ diff --git a/malloc/obstackv2.c b/malloc/obstackv2.c new file mode 100644 index 0000000..d8be95e --- /dev/null +++ b/malloc/obstackv2.c @@ -0,0 +1,69 @@ +/* obstackv2.c - subroutines used implicitly by object stack macros + Copyright (C) 2014 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, see + . */ + +/* Build version 2. */ +#define _OBSTACK_INTERFACE_VERSION 2 +#define _OBSTACK_C 1 + +#include "obstack.c" + +#ifndef _OBSTACK_ELIDE_CODE + +# ifdef _OBSTACK_ALIAS + +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_21) +# undef obstack_free +strong_alias (_obstack_free, obstackv1_free) +compat_symbol (libc, obstackv1_free, obstack_free, GLIBC_2_0); +# endif + +# 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 /* _OBSTACK_ALIAS */ + +libc_hidden_def (_obstack_newchunk) + +# ifdef _OBSTACK_COMPAT +# undef _obstack_allocated_p +# undef _obstack_begin +# undef _obstack_begin_1 +# undef _obstack_free +# undef _obstack_memory_used +# undef _obstack_newchunk + +# ifdef _OBSTACK_ALIAS +# define OB_VER GLIBC_2_0 +# else +# define OB_VER GLIBC_2_21 +# endif +versioned_symbol (libc, _obstackv2_allocated_p, _obstack_allocated_p, OB_VER); +versioned_symbol (libc, _obstackv2_begin, _obstack_begin, OB_VER); +versioned_symbol (libc, _obstackv2_begin_1, _obstack_begin_1, OB_VER); +versioned_symbol (libc, _obstackv2_free, _obstack_free, OB_VER); +versioned_symbol (libc, _obstackv2_memory_used, _obstack_memory_used, OB_VER); +versioned_symbol (libc, _obstackv2_newchunk, _obstack_newchunk, OB_VER); + +extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T); +libc_hidden_ver (_obstackv2_newchunk, _obstack_newchunk) +# endif /* _OBSTACK_COMPAT */ +#endif /* _OBSTACK_ELIDE_CODE */ diff --git a/malloc/obstack.c b/malloc/obstack.c index fa4fefc..8e247fb 100644 --- a/malloc/obstack.c +++ b/malloc/obstack.c @@ -19,16 +19,14 @@ #ifdef _LIBC # include -# include #else # include # 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 +/* 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. */ /* 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 @@ -38,20 +36,19 @@ (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 +# if (_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 #endif -#include - -#ifndef ELIDE_CODE - - +#ifndef _OBSTACK_ELIDE_CODE +# include # include /* Determine default alignment. */ @@ -75,42 +72,6 @@ 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); -void (*obstack_alloc_failed_handler) (void) = print_and_abort; - -/* Exit value used when 'print_and_abort' is used. */ -# include -# ifdef _LIBC -int obstack_exit_failure = EXIT_FAILURE; -# else -# include "exitfail.h" -# define obstack_exit_failure exit_failure -# endif - -# 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 /* Define a macro that either calls functions with the traditional malloc/free calling interface, or calls functions with the mmalloc/mfree interface @@ -121,7 +82,7 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); # define CALL_CHUNKFUN(h, size) \ (((h)->use_extra_arg) \ ? (*(h)->chunkfun)((h)->extra_arg, (size)) \ - : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size))) + : (*(struct _obstack_chunk *(*)(size_t))(h)->chunkfun)((size))) # define CALL_FREEFUN(h, old_chunk) \ do { \ @@ -140,11 +101,13 @@ 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_type) (void *, size_t); +typedef void (*freefun_type) (void *, struct _obstack_chunk *); + +static int +_obstack_begin_worker (struct obstack *h, + _OBSTACK_SIZE_T size, int alignment, + chunkfun_type chunkfun, freefun_type freefun) { struct _obstack_chunk *chunk; /* points to new chunk */ @@ -167,19 +130,17 @@ _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; 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 +149,29 @@ _obstack_begin (struct obstack *h, } int -_obstack_begin_1 (struct obstack *h, int size, int alignment, - void *(*chunkfun) (void *, long), - 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. */ +_obstack_begin (struct obstack *h, + _OBSTACK_SIZE_T size, int alignment, + void *(*chunkfun) (size_t), + void (*freefun) (void *)) { - /* 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->use_extra_arg = 0; + return _obstack_begin_worker (h, size, alignment, + (chunkfun_type) chunkfun, + (freefun_type) freefun); } - 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; +int +_obstack_begin_1 (struct obstack *h, + _OBSTACK_SIZE_T size, int alignment, + void *(*chunkfun) (void *, size_t), + void (*freefun) (void *, void *), + void *arg) +{ 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_type) chunkfun, + (freefun_type) freefun); } /* Allocate a new current chunk for the obstack *H @@ -242,14 +181,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, _OBSTACK_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. */ @@ -269,25 +206,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. @@ -306,9 +226,6 @@ _obstack_newchunk (struct obstack *h, int length) /* The new chunk certainly contains no empty object yet. */ h->maybe_empty_object = 0; } -# ifdef _LIBC -libc_hidden_def (_obstack_newchunk) -# endif /* Return nonzero if object OBJ has been allocated from obstack H. This is here for debugging. @@ -339,10 +256,8 @@ _obstack_allocated_p (struct obstack *h, void *obj) /* Free objects in obstack H, including OBJ and everything allocate more recently than OBJ. If OBJ is zero, free everything in H. */ -# undef obstack_free - void -__obstack_free (struct obstack *h, void *obj) +_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 */ @@ -371,17 +286,11 @@ __obstack_free (struct obstack *h, void *obj) abort (); } -# 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) -# endif - -int +_OBSTACK_SIZE_T _obstack_memory_used (struct obstack *h) { struct _obstack_chunk *lp; - int nbytes = 0; + _OBSTACK_SIZE_T nbytes = 0; for (lp = h->chunk; lp != 0; lp = lp->prev) { @@ -390,7 +299,18 @@ _obstack_memory_used (struct obstack *h) return nbytes; } +# ifndef _OBSTACK_NO_ERROR_HANDLER /* Define the error handler. */ +# include + +/* Exit value used when 'print_and_abort' is used. */ +# ifdef _LIBC +int obstack_exit_failure = EXIT_FAILURE; +# else +# include "exitfail.h" +# define obstack_exit_failure exit_failure +# endif + # ifdef _LIBC # include # else @@ -420,4 +340,12 @@ print_and_abort (void) exit (obstack_exit_failure); } -#endif /* !ELIDE_CODE */ +/* 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'. */ +void (*obstack_alloc_failed_handler) (void) = print_and_abort; +# endif /* !_OBSTACK_NO_ERROR_HANDLER */ +#endif /* !_OBSTACK_ELIDE_CODE */ diff --git a/malloc/obstack.h b/malloc/obstack.h index 59ae6e5..909d0d3 100644 --- a/malloc/obstack.h +++ b/malloc/obstack.h @@ -104,16 +104,22 @@ #ifndef _OBSTACK_H #define _OBSTACK_H 1 -/* 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 's symbols. Otherwise, include - and use ptrdiff_t. */ +#ifndef _OBSTACK_INTERFACE_VERSION +# define _OBSTACK_INTERFACE_VERSION 2 +#endif + +#include /* For size_t and ptrdiff_t. */ +#include /* For __GNU_LIBRARY__, and memcpy. */ -#ifdef __PTRDIFF_TYPE__ -# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#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 -# include -# define PTR_INT_TYPE ptrdiff_t +/* Version 2 with sane types, especially for 64-bit hosts. */ +# define _OBSTACK_SIZE_T size_t +# define _CHUNK_SIZE_T size_t #endif /* If B is the base of an object addressed by P, return the result of @@ -122,19 +128,17 @@ #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 ptrdiff_t 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 (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \ P, A) -#include - #ifndef __attribute_pure__ # define __attribute_pure__ _GL_ATTRIBUTE_PURE #endif @@ -152,21 +156,21 @@ struct _obstack_chunk /* Lives at front of each chunk. */ struct obstack /* control current object in current chunk */ { - long chunk_size; /* preferred size to allocate chunks in */ + _CHUNK_SIZE_T 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 */ union { - PTR_INT_TYPE tempint; - void *tempptr; + _OBSTACK_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 */ @@ -181,20 +185,15 @@ struct obstack /* control current object in current chunk */ /* 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), +extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T); +extern void _obstack_free (struct obstack *, void *); +extern int _obstack_begin (struct obstack *, _OBSTACK_SIZE_T, int, + void *(*)(size_t), void (*)(void *)); +extern int _obstack_begin_1 (struct obstack *, _OBSTACK_SIZE_T, int, + void *(*)(void *, size_t), void (*)(void *, void *), void *); -extern int _obstack_memory_used (struct obstack *) __attribute_pure__; - -/* 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 -#endif -extern void __obstack_free (struct obstack *, void *); +extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *) + __attribute_pure__; /* Error handler called when 'obstack_chunk_alloc' failed to allocate @@ -227,26 +226,26 @@ extern int obstack_exit_failure; /* To prevent prototype warnings provide complete argument list. */ #define obstack_init(h) \ _obstack_begin ((h), 0, 0, \ - (void *(*)(long))obstack_chunk_alloc, \ + (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 *(*)(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 *(*)(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 *, 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)) @@ -258,7 +257,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 @@ -270,18 +269,20 @@ extern int obstack_exit_failure; # define obstack_object_size(OBSTACK) \ __extension__ \ ({ struct obstack const *__o = (OBSTACK); \ - (unsigned) (__o->next_free - __o->object_base); }) + (_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 *__o = (OBSTACK); \ - (unsigned) (__o->chunk_limit - __o->next_free); }) + ({ struct obstack const *__o1 = (OBSTACK); \ + (_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->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_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ _obstack_newchunk (__o, __len); \ (void) 0; }) @@ -296,8 +297,8 @@ extern int obstack_exit_failure; # define obstack_grow(OBSTACK, where, length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->next_free + __len > __o->chunk_limit) \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ _obstack_newchunk (__o, __len); \ memcpy (__o->next_free, where, __len); \ __o->next_free += __len; \ @@ -306,8 +307,8 @@ extern int obstack_exit_failure; # define obstack_grow0(OBSTACK, where, length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _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; \ @@ -317,7 +318,7 @@ extern int obstack_exit_failure; # define obstack_1grow(OBSTACK, datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - if (__o->next_free + 1 > __o->chunk_limit) \ + if (obstack_room (__o) < 1) \ _obstack_newchunk (__o, 1); \ obstack_1grow_fast (__o, datum); \ (void) 0; }) @@ -329,14 +330,14 @@ extern int obstack_exit_failure; # define obstack_ptr_grow(OBSTACK, datum) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + if (obstack_room (__o) < sizeof (void *)) \ _obstack_newchunk (__o, sizeof (void *)); \ - obstack_ptr_grow_fast (__o, datum); }) \ + 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) \ + if (obstack_room (__o) < sizeof (int)) \ _obstack_newchunk (__o, sizeof (int)); \ obstack_int_grow_fast (__o, datum); }) @@ -359,8 +360,8 @@ extern int obstack_exit_failure; # define obstack_blank(OBSTACK, length) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - int __len = (length); \ - if (__o->chunk_limit - __o->next_free < __len) \ + _OBSTACK_SIZE_T __len = (length); \ + if (obstack_room (__o) < __len) \ _obstack_newchunk (__o, __len); \ obstack_blank_fast (__o, __len); \ (void) 0; }) @@ -383,8 +384,8 @@ extern int obstack_exit_failure; obstack_grow0 (__h, (where), (length)); \ obstack_finish (__h); }) -/* The local variable is named __o1 to avoid a name conflict - when obstack_blank is called. */ +/* The local variable is named __o1 to avoid a shadowed variable + warning when invoked from other obstack macros, typically obstack_free. */ # define obstack_finish(OBSTACK) \ __extension__ \ ({ struct obstack *__o1 = (OBSTACK); \ @@ -394,8 +395,8 @@ extern int obstack_exit_failure; __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) \ + 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; }) @@ -403,18 +404,19 @@ extern int obstack_exit_failure; # define obstack_free(OBSTACK, OBJ) \ __extension__ \ ({ struct obstack *__o = (OBSTACK); \ - void *__obj = (OBJ); \ + 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 \ + _obstack_free (__o, __obj); }) #else /* not __GNUC__ */ # define obstack_object_size(h) \ - (unsigned) ((h)->next_free - (h)->object_base) + ((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base)) # define obstack_room(h) \ - (unsigned) ((h)->chunk_limit - (h)->next_free) + ((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free)) # define obstack_empty_p(h) \ ((h)->chunk->prev == 0 \ @@ -429,37 +431,37 @@ extern int obstack_exit_failure; 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)) + ((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.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) + ((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.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)->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_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_room (h) < sizeof (char *)) \ ? (_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_room (h) < sizeof (int)) \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ obstack_int_grow_fast (h, datum)) @@ -470,10 +472,10 @@ extern int obstack_exit_failure; (((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)) + ((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) \ (obstack_blank ((h), (length)), obstack_finish ((h))) @@ -488,23 +490,22 @@ extern int obstack_exit_failure; (((h)->next_free == (h)->object_base \ ? (((h)->maybe_empty_object = 1), 0) \ : 0), \ - (h)->temp.tempptr = (h)->object_base, \ + (h)->temp.p = (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) \ + (((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.tempptr) + (h)->temp.p) # 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))) + ((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__ */ @@ -512,4 +513,4 @@ extern int obstack_exit_failure; } /* C++ */ #endif -#endif /* obstack.h */ +#endif /* _OBSTACK_H */