Update to glibc 2.38

This commit is contained in:
Daryl Ronningen 2023-12-08 01:20:08 -08:00
parent 362629706c
commit 8d47da6c5c
Signed by: Daryl Ronningen
GPG key ID: FD23F0C934A5EC6B
3 changed files with 351 additions and 329 deletions

View file

@ -1,8 +1,8 @@
dnl Process this file with autoconf to produce a configure script dnl Process this file with autoconf to produce a configure script
AC_PREREQ(2.69) AC_PREREQ([2.71])
AC_INIT([obstack], [1.2], [pullmoll@t-online.de]) AC_INIT([obstack],[1.3],[pullmoll@t-online.de])
AM_INIT_AUTOMAKE([1.16]) AM_INIT_AUTOMAKE([1.16])
AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_MACRO_DIR([m4])

353
obstack.c
View file

@ -1,5 +1,5 @@
/* obstack.c - subroutines used implicitly by object stack macros /* obstack.c - subroutines used implicitly by object stack macros
Copyright (C) 1988-2020 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -14,19 +14,21 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
#ifdef _LIBC #ifdef _LIBC
# include <obstack.h> # include <obstack.h>
# include <shlib-compat.h>
#else #else
# include <config.h> # include <config.h>
# include "obstack.h" # include "obstack.h"
#endif #endif
/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in /* NOTE BEFORE MODIFYING THIS FILE: This version number must be
obstack.h must be incremented whenever callers compiled using an old incremented whenever callers compiled using an old obstack.h can no
obstack.h can no longer properly call the functions in this file. */ longer properly call the functions in this obstack.c. */
#define OBSTACK_INTERFACE_VERSION 1
/* Comment out all this code if we are using the GNU C Library, and are not /* 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 actually compiling the library itself, and the installed library
@ -36,83 +38,108 @@
(especially if it is a shared library). Rather than having every GNU (especially if it is a shared library). Rather than having every GNU
program understand 'configure --with-gnu-libc' and omit the object 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. */ files, it is simpler to just do this in the source for each such file. */
#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1 #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
# include <gnu-versions.h> # include <gnu-versions.h>
# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \ # if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
|| (_GNU_OBSTACK_INTERFACE_VERSION == 1 \ # define ELIDE_CODE
&& _OBSTACK_INTERFACE_VERSION == 2 \
&& defined SIZEOF_INT && defined SIZEOF_SIZE_T \
&& SIZEOF_INT == SIZEOF_SIZE_T))
# define _OBSTACK_ELIDE_CODE
# endif # endif
#endif #endif
#ifndef _OBSTACK_ELIDE_CODE #include <stddef.h>
/* If GCC, or if an oddball (testing?) host that #defines __alignof__,
use the already-supplied __alignof__. Otherwise, this must be Gnulib #ifndef ELIDE_CODE
(as glibc assumes GCC); defer to Gnulib's alignof_type. */
# if !defined __GNUC__ && !defined __IBM__ALIGNOF__ && !defined __alignof__
# if defined __cplusplus
template <class type> struct alignof_helper { char __slot1; type __slot2; };
# define __alignof__(type) offsetof (alignof_helper<type>, __slot2)
# else
# define __alignof__(type) \
offsetof (struct { char __slot1; type __slot2; }, __slot2)
# endif
# endif
# include <stdlib.h>
# include <stdint.h> # include <stdint.h>
# ifndef MAX
# define MAX(a,b) ((a) > (b) ? (a) : (b))
# endif
/* Determine default alignment. */ /* Determine default alignment. */
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. /* 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 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. DEFAULT_ROUNDING. So we prepare for it to do that. */
enum
DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h. */
#define DEFAULT_ALIGNMENT MAX (__alignof__ (long double), \
MAX (__alignof__ (uintmax_t), \
__alignof__ (void *)))
#define DEFAULT_ROUNDING MAX (sizeof (long double), \
MAX (sizeof (uintmax_t), \
sizeof (void *)))
/* Call functions with either the traditional malloc/free calling
interface, or the mmalloc/mfree interface (that adds an extra first
argument), based on the value of use_extra_arg. */
static void *
call_chunkfun (struct obstack *h, size_t size)
{ {
if (h->use_extra_arg) DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
return h->chunkfun.extra (h->extra_arg, size); DEFAULT_ROUNDING = sizeof (union fooround)
else };
return h->chunkfun.plain (size);
}
static void /* When we copy a long block of data, this is the unit to do it with.
call_freefun (struct obstack *h, void *old_chunk) On some machines, copying successive ints does not work;
{ in such a case, redefine COPYING_UNIT to 'long' (if that works)
if (h->use_extra_arg) or 'char' as a last resort. */
h->freefun.extra (h->extra_arg, old_chunk); # ifndef COPYING_UNIT
else # define COPYING_UNIT int
h->freefun.plain (old_chunk); # 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 <stdlib.h>
int obstack_exit_failure = EXIT_FAILURE;
# 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
(that adds an extra first argument), based on the state of use_extra_arg.
For free, do not use ?:, since some compilers, like the MIPS compilers,
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)))
# 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)
/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
Objects start on multiples of ALIGNMENT (0 means use default). Objects start on multiples of ALIGNMENT (0 means use default).
CHUNKFUN is the function to use to allocate chunks,
and FREEFUN the function to free them.
Return nonzero if successful, calls obstack_alloc_failed_handler if Return nonzero if successful, calls obstack_alloc_failed_handler if
allocation fails. */ allocation fails. */
static int int
_obstack_begin_worker (struct obstack *h, _obstack_begin (struct obstack *h,
_OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment) int size, int alignment,
void *(*chunkfun) (long),
void (*freefun) (void *))
{ {
struct _obstack_chunk *chunk; /* points to new chunk */ struct _obstack_chunk *chunk; /* points to new chunk */
@ -122,29 +149,32 @@ _obstack_begin_worker (struct obstack *h,
/* Default size is what GNU malloc can fit in a 4096-byte block. */ /* Default size is what GNU malloc can fit in a 4096-byte block. */
{ {
/* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
Use the values for range checking, because if range checking is off, 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 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 and we used a larger request, a whole extra 4096 bytes would be
allocated. allocated.
These number are irrelevant to the new GNU malloc. I suspect it is These number are irrelevant to the new GNU malloc. I suspect it is
less sensitive to the size of the request. */ less sensitive to the size of the request. */
int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
+ 4 + DEFAULT_ROUNDING - 1) + 4 + DEFAULT_ROUNDING - 1)
& ~(DEFAULT_ROUNDING - 1)); & ~(DEFAULT_ROUNDING - 1));
size = 4096 - extra; size = 4096 - extra;
} }
h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
h->chunk_size = size; h->chunk_size = size;
h->alignment_mask = alignment - 1; h->alignment_mask = alignment - 1;
h->use_extra_arg = 0;
chunk = (struct _obstack_chunk *) call_chunkfun (h, h->chunk_size); chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
if (!chunk) if (!chunk)
(*obstack_alloc_failed_handler) (); (*obstack_alloc_failed_handler) ();
h->chunk = chunk;
h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
alignment - 1); 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; chunk->prev = 0;
/* The initial chunk now contains no empty object. */ /* The initial chunk now contains no empty object. */
h->maybe_empty_object = 0; h->maybe_empty_object = 0;
@ -153,29 +183,51 @@ _obstack_begin_worker (struct obstack *h,
} }
int int
_obstack_begin (struct obstack *h, _obstack_begin_1 (struct obstack *h, int size, int alignment,
_OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment, void *(*chunkfun) (void *, long),
void *(*chunkfun) (size_t), void (*freefun) (void *, void *),
void (*freefun) (void *)) void *arg)
{ {
h->chunkfun.plain = chunkfun; struct _obstack_chunk *chunk; /* points to new chunk */
h->freefun.plain = freefun;
h->use_extra_arg = 0;
return _obstack_begin_worker (h, size, alignment);
}
int if (alignment == 0)
_obstack_begin_1 (struct obstack *h, alignment = DEFAULT_ALIGNMENT;
_OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment, if (size == 0)
void *(*chunkfun) (void *, size_t), /* Default size is what GNU malloc can fit in a 4096-byte block. */
void (*freefun) (void *, void *), {
void *arg) /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
{ Use the values for range checking, because if range checking is off,
h->chunkfun.extra = chunkfun; the extra bytes won't be missed terribly, but if range checking is on
h->freefun.extra = freefun; 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->extra_arg = arg;
h->use_extra_arg = 1; h->use_extra_arg = 1;
return _obstack_begin_worker (h, size, alignment);
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;
} }
/* Allocate a new current chunk for the obstack *H /* Allocate a new current chunk for the obstack *H
@ -185,25 +237,23 @@ _obstack_begin_1 (struct obstack *h,
to the beginning of the new one. */ to the beginning of the new one. */
void void
_obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length) _obstack_newchunk (struct obstack *h, int length)
{ {
struct _obstack_chunk *old_chunk = h->chunk; struct _obstack_chunk *old_chunk = h->chunk;
struct _obstack_chunk *new_chunk = 0; struct _obstack_chunk *new_chunk;
size_t obj_size = h->next_free - h->object_base; long new_size;
long obj_size = h->next_free - h->object_base;
long i;
long already;
char *object_base; char *object_base;
/* Compute size for new chunk. */ /* Compute size for new chunk. */
size_t sum1 = obj_size + length; new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
size_t sum2 = sum1 + h->alignment_mask;
size_t new_size = sum2 + (obj_size >> 3) + 100;
if (new_size < sum2)
new_size = sum2;
if (new_size < h->chunk_size) if (new_size < h->chunk_size)
new_size = h->chunk_size; new_size = h->chunk_size;
/* Allocate and initialize the new chunk. */ /* Allocate and initialize the new chunk. */
if (obj_size <= sum1 && sum1 <= sum2) new_chunk = CALL_CHUNKFUN (h, new_size);
new_chunk = (struct _obstack_chunk *) call_chunkfun (h, new_size);
if (!new_chunk) if (!new_chunk)
(*obstack_alloc_failed_handler)(); (*obstack_alloc_failed_handler)();
h->chunk = new_chunk; h->chunk = new_chunk;
@ -214,19 +264,36 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
object_base = object_base =
__PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
/* Move the existing object to the new chunk. */ /* Move the existing object to the new chunk.
memcpy (object_base, h->object_base, obj_size); 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];
/* If the object just copied was the only data in OLD_CHUNK, /* If the object just copied was the only data in OLD_CHUNK,
free that chunk and remove it from the chain. free that chunk and remove it from the chain.
But not if that chunk might contain an empty object. */ But not if that chunk might contain an empty object. */
if (!h->maybe_empty_object if (!h->maybe_empty_object
&& (h->object_base && (h->object_base
== __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
h->alignment_mask))) h->alignment_mask)))
{ {
new_chunk->prev = old_chunk->prev; new_chunk->prev = old_chunk->prev;
call_freefun (h, old_chunk); CALL_FREEFUN (h, old_chunk);
} }
h->object_base = object_base; h->object_base = object_base;
@ -234,6 +301,9 @@ _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
/* The new chunk certainly contains no empty object yet. */ /* The new chunk certainly contains no empty object yet. */
h->maybe_empty_object = 0; h->maybe_empty_object = 0;
} }
# ifdef _LIBC
libc_hidden_def (_obstack_newchunk)
# endif
/* Return nonzero if object OBJ has been allocated from obstack H. /* Return nonzero if object OBJ has been allocated from obstack H.
This is here for debugging. This is here for debugging.
@ -264,8 +334,10 @@ _obstack_allocated_p (struct obstack *h, void *obj)
/* Free objects in obstack H, including OBJ and everything allocate /* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */ more recently than OBJ. If OBJ is zero, free everything in H. */
# undef obstack_free
void 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 *lp; /* below addr of any objects in this chunk */
struct _obstack_chunk *plp; /* point to previous chunk if any */ struct _obstack_chunk *plp; /* point to previous chunk if any */
@ -277,10 +349,10 @@ _obstack_free (struct obstack *h, void *obj)
while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
{ {
plp = lp->prev; plp = lp->prev;
call_freefun (h, lp); CALL_FREEFUN (h, lp);
lp = plp; lp = plp;
/* If we switch chunks, we can't tell whether the new current /* If we switch chunks, we can't tell whether the new current
chunk contains an empty object, so assume that it may. */ chunk contains an empty object, so assume that it may. */
h->maybe_empty_object = 1; h->maybe_empty_object = 1;
} }
if (lp) if (lp)
@ -294,13 +366,17 @@ _obstack_free (struct obstack *h, void *obj)
abort (); abort ();
} }
extern __typeof(_obstack_free) obstack_free __attribute__((alias("_obstack_free"))); # 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
_OBSTACK_SIZE_T int
_obstack_memory_used (struct obstack *h) _obstack_memory_used (struct obstack *h)
{ {
struct _obstack_chunk *lp; struct _obstack_chunk *lp;
_OBSTACK_SIZE_T nbytes = 0; int nbytes = 0;
for (lp = h->chunk; lp != 0; lp = lp->prev) for (lp = h->chunk; lp != 0; lp = lp->prev)
{ {
@ -309,20 +385,6 @@ _obstack_memory_used (struct obstack *h)
return nbytes; return nbytes;
} }
# ifndef _OBSTACK_NO_ERROR_HANDLER
/* Define the error handler. */
# include <stdio.h>
/* Exit value used when 'print_and_abort' is used. */
# ifdef _LIBC
int obstack_exit_failure = EXIT_FAILURE;
# else
# ifndef EXIT_FAILURE
# define EXIT_FAILURE 1
# endif
# define obstack_exit_failure EXIT_FAILURE
# endif
# if defined _LIBC || (HAVE_LIBINTL_H && ENABLE_NLS) # if defined _LIBC || (HAVE_LIBINTL_H && ENABLE_NLS)
# include <libintl.h> # include <libintl.h>
# ifndef _ # ifndef _
@ -334,22 +396,9 @@ int obstack_exit_failure = EXIT_FAILURE;
# endif # endif
# endif # endif
# if !(defined _Noreturn \ # ifdef _LIBC
|| (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112)) # include <libio/iolibio.h>
# if ((defined __GNUC__ \ # endif
&& (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))) \
|| (defined __SUNPRO_C && __SUNPRO_C >= 0x5110))
# define _Noreturn __attribute__ ((__noreturn__))
# elif defined _MSC_VER && _MSC_VER >= 1200
# define _Noreturn __declspec (noreturn)
# else
# define _Noreturn
# endif
# endif
# ifdef _LIBC
# include <libio/iolibio.h>
# endif
static _Noreturn void static _Noreturn void
print_and_abort (void) print_and_abort (void)
@ -359,20 +408,12 @@ print_and_abort (void)
happen because the "memory exhausted" message appears in other places happen because the "memory exhausted" message appears in other places
like this and the translation should be reused instead of creating like this and the translation should be reused instead of creating
a very similar string which requires a separate translation. */ a very similar string which requires a separate translation. */
# ifdef _LIBC # ifdef _LIBC
(void) __fxprintf (NULL, "%s\n", _("memory exhausted")); (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
# else # else
fprintf (stderr, "%s\n", _("memory exhausted")); fprintf (stderr, "%s\n", _("memory exhausted"));
# endif # endif
exit (obstack_exit_failure); exit (obstack_exit_failure);
} }
/* The functions allocating more room by calling 'obstack_chunk_alloc' #endif /* !ELIDE_CODE */
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 */

323
obstack.h
View file

@ -1,5 +1,5 @@
/* obstack.h - object stack macros /* obstack.h - object stack macros
Copyright (C) 1988-2020 Free Software Foundation, Inc. Copyright (C) 1988-2023 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or The GNU C Library is free software; you can redistribute it and/or
@ -14,7 +14,7 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */ <https://www.gnu.org/licenses/>. */
/* Summary: /* Summary:
@ -85,17 +85,17 @@
break the ordinary 'growth' macro. break the ordinary 'growth' macro.
Summary: Summary:
We allocate large chunks. We allocate large chunks.
We carve out one object at a time from the current chunk. We carve out one object at a time from the current chunk.
Once carved, an object never moves. Once carved, an object never moves.
We are free to append data of any size to the currently We are free to append data of any size to the currently
growing object. growing object.
Exactly one object is growing in an obstack at any one time. Exactly one object is growing in an obstack at any one time.
You can run one obstack per control block. You can run one obstack per control block.
You may have as many control blocks as you dare. You may have as many control blocks as you dare.
Because of the way we do it, you can "unwind" an obstack Because of the way we do it, you can "unwind" an obstack
back to a previous state. (You may remove objects much back to a previous state. (You may remove objects much
as you would with a stack.) as you would with a stack.)
*/ */
@ -104,24 +104,16 @@
#ifndef _OBSTACK_H #ifndef _OBSTACK_H
#define _OBSTACK_H 1 #define _OBSTACK_H 1
#ifndef _OBSTACK_INTERFACE_VERSION /* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is
# define _OBSTACK_INTERFACE_VERSION 2 defined, as with GNU C, use that; that way we don't pollute the
#endif namespace with <stddef.h>'s symbols. Otherwise, include <stddef.h>
and use ptrdiff_t. */
#include <stddef.h> /* For size_t and ptrdiff_t. */ #ifdef __PTRDIFF_TYPE__
#include <string.h> /* For __GNU_LIBRARY__, and memcpy. */ # 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
# define _OBSTACK_CAST(type, expr) ((type) (expr))
#else #else
/* Version 2 with sane types, especially for 64-bit hosts. */ # include <stddef.h>
# define _OBSTACK_SIZE_T size_t # define PTR_INT_TYPE ptrdiff_t
# define _CHUNK_SIZE_T size_t
# define _OBSTACK_CAST(type, expr) (expr)
#endif #endif
/* If B is the base of an object addressed by P, return the result of /* If B is the base of an object addressed by P, return the result of
@ -130,16 +122,18 @@
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) #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, where pointers can be converted to integers, aligned as integers,
and converted back again. If ptrdiff_t 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 pointer (e.g., the AS/400), play it safe and compute the alignment
relative to B. Otherwise, use the faster strategy of computing the relative to B. Otherwise, use the faster strategy of computing the
alignment relative to 0. */ alignment relative to 0. */
#define __PTR_ALIGN(B, P, A) \ #define __PTR_ALIGN(B, P, A) \
__BPTR_ALIGN (sizeof (ptrdiff_t) < sizeof (void *) ? (B) : (char *) 0, \ __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
P, A) P, A)
#include <string.h>
#ifndef __attribute_pure__ #ifndef __attribute_pure__
# if defined __GNUC_MINOR__ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2096 # if defined __GNUC_MINOR__ && __GNUC__ * 1000 + __GNUC_MINOR__ >= 2096
@ -162,57 +156,49 @@ struct _obstack_chunk /* Lives at front of each chunk. */
struct obstack /* control current object in current chunk */ struct obstack /* control current object in current chunk */
{ {
_CHUNK_SIZE_T chunk_size; /* preferred size to allocate chunks in */ long chunk_size; /* preferred size to allocate chunks in */
struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
char *object_base; /* address of object we are building */ char *object_base; /* address of object we are building */
char *next_free; /* where to add next char to current object */ char *next_free; /* where to add next char to current object */
char *chunk_limit; /* address of char after current chunk */ char *chunk_limit; /* address of char after current chunk */
union union
{ {
_OBSTACK_SIZE_T i; PTR_INT_TYPE tempint;
void *p; void *tempptr;
} temp; /* Temporary for some macros. */ } temp; /* Temporary for some macros. */
_OBSTACK_SIZE_T alignment_mask; /* Mask of alignment for each object. */ int alignment_mask; /* Mask of alignment for each object. */
/* These prototypes vary based on 'use_extra_arg', and we use
/* These prototypes vary based on 'use_extra_arg'. */ casts to the prototypeless function type in all assignments,
union but having prototypes here quiets -Wstrict-prototypes. */
{ struct _obstack_chunk *(*chunkfun) (void *, long);
void *(*plain) (size_t); void (*freefun) (void *, struct _obstack_chunk *);
void *(*extra) (void *, size_t);
} chunkfun;
union
{
void (*plain) (void *);
void (*extra) (void *, void *);
} freefun;
void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ void *extra_arg; /* first arg for chunk alloc/dealloc funcs */
unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */ unsigned use_extra_arg : 1; /* chunk alloc/dealloc funcs take extra arg */
unsigned maybe_empty_object : 1; /* There is a possibility that the current unsigned maybe_empty_object : 1; /* There is a possibility that the current
chunk contains a zero-length object. This chunk contains a zero-length object. This
prevents freeing the chunk if we allocate prevents freeing the chunk if we allocate
a bigger chunk to replace it. */ 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 handler on error, but retained for binary
compatibility. */ compatibility. */
}; };
/* Declare the external functions we use; they are in obstack.c. */ /* Declare the external functions we use; they are in obstack.c. */
extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T); extern void _obstack_newchunk (struct obstack *, int);
extern void _obstack_free (struct obstack *, void *); extern int _obstack_begin (struct obstack *, int, int,
extern int _obstack_begin (struct obstack *, void *(*)(long), void (*)(void *));
_OBSTACK_SIZE_T, _OBSTACK_SIZE_T, extern int _obstack_begin_1 (struct obstack *, int, int,
void *(*) (size_t), void (*) (void *)); void *(*)(void *, long),
extern int _obstack_begin_1 (struct obstack *, void (*)(void *, void *), void *);
_OBSTACK_SIZE_T, _OBSTACK_SIZE_T, extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
void *(*) (void *, size_t),
void (*) (void *, void *), void *);
extern _OBSTACK_SIZE_T _obstack_memory_used (struct obstack *)
__attribute_pure__;
/* Declare obstack_printf; it's in obstack_printf.c. */ /* The default name of the function for freeing a chunk is 'obstack_free',
extern int obstack_printf(struct obstack *obstack, const char *__restrict fmt, ...); 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 *);
/* Error handler called when 'obstack_chunk_alloc' failed to allocate /* Error handler called when 'obstack_chunk_alloc' failed to allocate
@ -236,7 +222,7 @@ extern int obstack_exit_failure;
/* Pointer to next byte not yet allocated in current chunk. */ /* Pointer to next byte not yet allocated in current chunk. */
#define obstack_next_free(h) ((void *) (h)->next_free) #define obstack_next_free(h) ((h)->next_free)
/* Mask specifying low bits that should be clear in address of an object. */ /* Mask specifying low bits that should be clear in address of an object. */
@ -245,38 +231,38 @@ extern int obstack_exit_failure;
/* To prevent prototype warnings provide complete argument list. */ /* To prevent prototype warnings provide complete argument list. */
#define obstack_init(h) \ #define obstack_init(h) \
_obstack_begin ((h), 0, 0, \ _obstack_begin ((h), 0, 0, \
_OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \ (void *(*)(long))obstack_chunk_alloc, \
_OBSTACK_CAST (void (*) (void *), obstack_chunk_free)) (void (*)(void *))obstack_chunk_free)
#define obstack_begin(h, size) \ #define obstack_begin(h, size) \
_obstack_begin ((h), (size), 0, \ _obstack_begin ((h), (size), 0, \
_OBSTACK_CAST (void *(*) (size_t), obstack_chunk_alloc), \ (void *(*)(long))obstack_chunk_alloc, \
_OBSTACK_CAST (void (*) (void *), obstack_chunk_free)) (void (*)(void *))obstack_chunk_free)
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ #define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \
_obstack_begin ((h), (size), (alignment), \ _obstack_begin ((h), (size), (alignment), \
_OBSTACK_CAST (void *(*) (size_t), chunkfun), \ (void *(*)(long))(chunkfun), \
_OBSTACK_CAST (void (*) (void *), freefun)) (void (*)(void *))(freefun))
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ #define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
_obstack_begin_1 ((h), (size), (alignment), \ _obstack_begin_1 ((h), (size), (alignment), \
_OBSTACK_CAST (void *(*) (void *, size_t), chunkfun), \ (void *(*)(void *, long))(chunkfun), \
_OBSTACK_CAST (void (*) (void *, void *), freefun), arg) (void (*)(void *, void *))(freefun), (arg))
#define obstack_chunkfun(h, newchunkfun) \ #define obstack_chunkfun(h, newchunkfun) \
((void) ((h)->chunkfun.extra = (void *(*) (void *, size_t)) (newchunkfun))) ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
#define obstack_freefun(h, newfreefun) \ #define obstack_freefun(h, newfreefun) \
((void) ((h)->freefun.extra = (void *(*) (void *, void *)) (newfreefun))) ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
#define obstack_1grow_fast(h, achar) ((void) (*((h)->next_free)++ = (achar))) #define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
#define obstack_blank_fast(h, n) ((void) ((h)->next_free += (n))) #define obstack_blank_fast(h, n) ((h)->next_free += (n))
#define obstack_memory_used(h) _obstack_memory_used (h) #define obstack_memory_used(h) _obstack_memory_used (h)
#if defined __GNUC__ #if defined __GNUC__
# if !defined __GNUC_MINOR__ || __GNUC__ * 1000 + __GNUC_MINOR__ < 2008 # if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
# define __extension__ # define __extension__
# endif # endif
@ -288,37 +274,35 @@ extern int obstack_exit_failure;
# define obstack_object_size(OBSTACK) \ # define obstack_object_size(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(_OBSTACK_SIZE_T) (__o->next_free - __o->object_base); }) (unsigned) (__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) \ # define obstack_room(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o1 = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(_OBSTACK_SIZE_T) (__o1->chunk_limit - __o1->next_free); }) (unsigned) (__o->chunk_limit - __o->next_free); })
# define obstack_make_room(OBSTACK, length) \ # define obstack_make_room(OBSTACK, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
_OBSTACK_SIZE_T __len = (length); \ int __len = (length); \
if (obstack_room (__o) < __len) \ if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
(void) 0; }) (void) 0; })
# define obstack_empty_p(OBSTACK) \ # define obstack_empty_p(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack const *__o = (OBSTACK); \ ({ struct obstack const *__o = (OBSTACK); \
(__o->chunk->prev == 0 \ (__o->chunk->prev == 0 \
&& __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \
__o->chunk->contents, \ __o->chunk->contents, \
__o->alignment_mask)); }) __o->alignment_mask)); })
# define obstack_grow(OBSTACK, where, length) \ # define obstack_grow(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
_OBSTACK_SIZE_T __len = (length); \ int __len = (length); \
if (obstack_room (__o) < __len) \ if (__o->next_free + __len > __o->chunk_limit) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
memcpy (__o->next_free, where, __len); \ memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \ __o->next_free += __len; \
(void) 0; }) (void) 0; })
@ -326,9 +310,9 @@ extern int obstack_exit_failure;
# define obstack_grow0(OBSTACK, where, length) \ # define obstack_grow0(OBSTACK, where, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
_OBSTACK_SIZE_T __len = (length); \ int __len = (length); \
if (obstack_room (__o) < __len + 1) \ if (__o->next_free + __len + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, __len + 1); \ _obstack_newchunk (__o, __len + 1); \
memcpy (__o->next_free, where, __len); \ memcpy (__o->next_free, where, __len); \
__o->next_free += __len; \ __o->next_free += __len; \
*(__o->next_free)++ = 0; \ *(__o->next_free)++ = 0; \
@ -337,9 +321,10 @@ extern int obstack_exit_failure;
# define obstack_1grow(OBSTACK, datum) \ # define obstack_1grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (obstack_room (__o) < 1) \ if (__o->next_free + 1 > __o->chunk_limit) \
_obstack_newchunk (__o, 1); \ _obstack_newchunk (__o, 1); \
obstack_1grow_fast (__o, datum); }) obstack_1grow_fast (__o, datum); \
(void) 0; })
/* These assume that the obstack alignment is good enough for pointers /* These assume that the obstack alignment is good enough for pointers
or ints, and that the data added so far to the current object or ints, and that the data added so far to the current object
@ -348,15 +333,15 @@ extern int obstack_exit_failure;
# define obstack_ptr_grow(OBSTACK, datum) \ # define obstack_ptr_grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (obstack_room (__o) < sizeof (void *)) \ if (__o->next_free + sizeof (void *) > __o->chunk_limit) \
_obstack_newchunk (__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) \ # define obstack_int_grow(OBSTACK, datum) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
if (obstack_room (__o) < sizeof (int)) \ if (__o->next_free + sizeof (int) > __o->chunk_limit) \
_obstack_newchunk (__o, sizeof (int)); \ _obstack_newchunk (__o, sizeof (int)); \
obstack_int_grow_fast (__o, datum); }) obstack_int_grow_fast (__o, datum); })
# define obstack_ptr_grow_fast(OBSTACK, aptr) \ # define obstack_ptr_grow_fast(OBSTACK, aptr) \
@ -378,10 +363,11 @@ extern int obstack_exit_failure;
# define obstack_blank(OBSTACK, length) \ # define obstack_blank(OBSTACK, length) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
_OBSTACK_SIZE_T __len = (length); \ int __len = (length); \
if (obstack_room (__o) < __len) \ if (__o->chunk_limit - __o->next_free < __len) \
_obstack_newchunk (__o, __len); \ _obstack_newchunk (__o, __len); \
obstack_blank_fast (__o, __len); }) obstack_blank_fast (__o, __len); \
(void) 0; })
# define obstack_alloc(OBSTACK, length) \ # define obstack_alloc(OBSTACK, length) \
__extension__ \ __extension__ \
@ -401,45 +387,44 @@ extern int obstack_exit_failure;
obstack_grow0 (__h, (where), (length)); \ obstack_grow0 (__h, (where), (length)); \
obstack_finish (__h); }) obstack_finish (__h); })
/* The local variable is named __o1 to avoid a shadowed variable /* The local variable is named __o1 to avoid a name conflict
warning when invoked from other obstack macros, typically obstack_free. */ when obstack_blank is called. */
# define obstack_finish(OBSTACK) \ # define obstack_finish(OBSTACK) \
__extension__ \ __extension__ \
({ struct obstack *__o1 = (OBSTACK); \ ({ struct obstack *__o1 = (OBSTACK); \
void *__value = (void *) __o1->object_base; \ void *__value = (void *) __o1->object_base; \
if (__o1->next_free == __value) \ if (__o1->next_free == __value) \
__o1->maybe_empty_object = 1; \ __o1->maybe_empty_object = 1; \
__o1->next_free \ __o1->next_free \
= __PTR_ALIGN (__o1->object_base, __o1->next_free, \ = __PTR_ALIGN (__o1->object_base, __o1->next_free, \
__o1->alignment_mask); \ __o1->alignment_mask); \
if ((size_t) (__o1->next_free - (char *) __o1->chunk) \ if (__o1->next_free - (char *) __o1->chunk \
> (size_t) (__o1->chunk_limit - (char *) __o1->chunk)) \ > __o1->chunk_limit - (char *) __o1->chunk) \
__o1->next_free = __o1->chunk_limit; \ __o1->next_free = __o1->chunk_limit; \
__o1->object_base = __o1->next_free; \ __o1->object_base = __o1->next_free; \
__value; }) __value; })
# define obstack_free(OBSTACK, OBJ) \ # define obstack_free(OBSTACK, OBJ) \
__extension__ \ __extension__ \
({ struct obstack *__o = (OBSTACK); \ ({ struct obstack *__o = (OBSTACK); \
void *__obj = (void *) (OBJ); \ void *__obj = (OBJ); \
if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \ if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit) \
__o->next_free = __o->object_base = (char *) __obj; \ __o->next_free = __o->object_base = (char *) __obj; \
else \ else (__obstack_free) (__o, __obj); })
_obstack_free (__o, __obj); })
#else /* not __GNUC__ */ #else /* not __GNUC__ */
# define obstack_object_size(h) \ # define obstack_object_size(h) \
((_OBSTACK_SIZE_T) ((h)->next_free - (h)->object_base)) (unsigned) ((h)->next_free - (h)->object_base)
# define obstack_room(h) \ # define obstack_room(h) \
((_OBSTACK_SIZE_T) ((h)->chunk_limit - (h)->next_free)) (unsigned) ((h)->chunk_limit - (h)->next_free)
# define obstack_empty_p(h) \ # define obstack_empty_p(h) \
((h)->chunk->prev == 0 \ ((h)->chunk->prev == 0 \
&& (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \
(h)->chunk->contents, \ (h)->chunk->contents, \
(h)->alignment_mask)) (h)->alignment_mask))
/* Note that the call to _obstack_newchunk is enclosed in (..., 0) /* Note that the call to _obstack_newchunk is enclosed in (..., 0)
so that we can avoid having void expressions so that we can avoid having void expressions
@ -448,56 +433,51 @@ extern int obstack_exit_failure;
but some compilers won't accept it. */ but some compilers won't accept it. */
# define obstack_make_room(h, length) \ # define obstack_make_room(h, length) \
((h)->temp.i = (length), \ ((h)->temp.tempint = (length), \
((obstack_room (h) < (h)->temp.i) \ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
? (_obstack_newchunk (h, (h)->temp.i), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
(void) 0)
# define obstack_grow(h, where, length) \ # define obstack_grow(h, where, length) \
((h)->temp.i = (length), \ ((h)->temp.tempint = (length), \
((obstack_room (h) < (h)->temp.i) \ (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.i), \ memcpy ((h)->next_free, where, (h)->temp.tempint), \
(h)->next_free += (h)->temp.i, \ (h)->next_free += (h)->temp.tempint)
(void) 0)
# define obstack_grow0(h, where, length) \ # define obstack_grow0(h, where, length) \
((h)->temp.i = (length), \ ((h)->temp.tempint = (length), \
((obstack_room (h) < (h)->temp.i + 1) \ (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), (h)->temp.i + 1), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \
memcpy ((h)->next_free, where, (h)->temp.i), \ memcpy ((h)->next_free, where, (h)->temp.tempint), \
(h)->next_free += (h)->temp.i, \ (h)->next_free += (h)->temp.tempint, \
*((h)->next_free)++ = 0, \ *((h)->next_free)++ = 0)
(void) 0)
# define obstack_1grow(h, datum) \ # define obstack_1grow(h, datum) \
(((obstack_room (h) < 1) \ ((((h)->next_free + 1 > (h)->chunk_limit) \
? (_obstack_newchunk ((h), 1), 0) : 0), \ ? (_obstack_newchunk ((h), 1), 0) : 0), \
obstack_1grow_fast (h, datum)) obstack_1grow_fast (h, datum))
# define obstack_ptr_grow(h, datum) \ # define obstack_ptr_grow(h, datum) \
(((obstack_room (h) < sizeof (char *)) \ ((((h)->next_free + sizeof (char *) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \
obstack_ptr_grow_fast (h, datum)) obstack_ptr_grow_fast (h, datum))
# define obstack_int_grow(h, datum) \ # define obstack_int_grow(h, datum) \
(((obstack_room (h) < sizeof (int)) \ ((((h)->next_free + sizeof (int) > (h)->chunk_limit) \
? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \
obstack_int_grow_fast (h, datum)) 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), \ (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
(void) 0)
# define obstack_int_grow_fast(h, aint) \ # define obstack_int_grow_fast(h, aint) \
(((int *) ((h)->next_free += sizeof (int)))[-1] = (aint), \ (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
(void) 0)
# define obstack_blank(h, length) \ # define obstack_blank(h, length) \
((h)->temp.i = (length), \ ((h)->temp.tempint = (length), \
((obstack_room (h) < (h)->temp.i) \ (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \
? (_obstack_newchunk ((h), (h)->temp.i), 0) : 0), \ ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \
obstack_blank_fast (h, (h)->temp.i)) obstack_blank_fast (h, (h)->temp.tempint))
# define obstack_alloc(h, length) \ # define obstack_alloc(h, length) \
(obstack_blank ((h), (length)), obstack_finish ((h))) (obstack_blank ((h), (length)), obstack_finish ((h)))
@ -512,22 +492,23 @@ extern int obstack_exit_failure;
(((h)->next_free == (h)->object_base \ (((h)->next_free == (h)->object_base \
? (((h)->maybe_empty_object = 1), 0) \ ? (((h)->maybe_empty_object = 1), 0) \
: 0), \ : 0), \
(h)->temp.p = (h)->object_base, \ (h)->temp.tempptr = (h)->object_base, \
(h)->next_free \ (h)->next_free \
= __PTR_ALIGN ((h)->object_base, (h)->next_free, \ = __PTR_ALIGN ((h)->object_base, (h)->next_free, \
(h)->alignment_mask), \ (h)->alignment_mask), \
(((size_t) ((h)->next_free - (char *) (h)->chunk) \ (((h)->next_free - (char *) (h)->chunk \
> (size_t) ((h)->chunk_limit - (char *) (h)->chunk)) \ > (h)->chunk_limit - (char *) (h)->chunk) \
? ((h)->next_free = (h)->chunk_limit) : 0), \ ? ((h)->next_free = (h)->chunk_limit) : 0), \
(h)->object_base = (h)->next_free, \ (h)->object_base = (h)->next_free, \
(h)->temp.p) (h)->temp.tempptr)
# define obstack_free(h, obj) \ # define obstack_free(h, obj) \
((h)->temp.p = (void *) (obj), \ ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \
(((h)->temp.p > (void *) (h)->chunk \ ((((h)->temp.tempint > 0 \
&& (h)->temp.p < (void *) (h)->chunk_limit) \ && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \
? (void) ((h)->next_free = (h)->object_base = (char *) (h)->temp.p) \ ? (void) ((h)->next_free = (h)->object_base \
: _obstack_free ((h), (h)->temp.p))) = (h)->temp.tempint + (char *) (h)->chunk) \
: (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
#endif /* not __GNUC__ */ #endif /* not __GNUC__ */
@ -535,4 +516,4 @@ extern int obstack_exit_failure;
} /* C++ */ } /* C++ */
#endif #endif
#endif /* _OBSTACK_H */ #endif /* obstack.h */