Blame malloc/obstack.h

Packit 6c4009
/* obstack.h - object stack macros
Packit 6c4009
   Copyright (C) 1988-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
/* Summary:
Packit 6c4009
Packit 6c4009
   All the apparent functions defined here are macros. The idea
Packit 6c4009
   is that you would use these pre-tested macros to solve a
Packit 6c4009
   very specific set of problems, and they would run fast.
Packit 6c4009
   Caution: no side-effects in arguments please!! They may be
Packit 6c4009
   evaluated MANY times!!
Packit 6c4009
Packit 6c4009
   These macros operate a stack of objects.  Each object starts life
Packit 6c4009
   small, and may grow to maturity.  (Consider building a word syllable
Packit 6c4009
   by syllable.)  An object can move while it is growing.  Once it has
Packit 6c4009
   been "finished" it never changes address again.  So the "top of the
Packit 6c4009
   stack" is typically an immature growing object, while the rest of the
Packit 6c4009
   stack is of mature, fixed size and fixed address objects.
Packit 6c4009
Packit 6c4009
   These routines grab large chunks of memory, using a function you
Packit 6c4009
   supply, called 'obstack_chunk_alloc'.  On occasion, they free chunks,
Packit 6c4009
   by calling 'obstack_chunk_free'.  You must define them and declare
Packit 6c4009
   them before using any obstack macros.
Packit 6c4009
Packit 6c4009
   Each independent stack is represented by a 'struct obstack'.
Packit 6c4009
   Each of the obstack macros expects a pointer to such a structure
Packit 6c4009
   as the first argument.
Packit 6c4009
Packit 6c4009
   One motivation for this package is the problem of growing char strings
Packit 6c4009
   in symbol tables.  Unless you are "fascist pig with a read-only mind"
Packit 6c4009
   --Gosper's immortal quote from HAKMEM item 154, out of context--you
Packit 6c4009
   would not like to put any arbitrary upper limit on the length of your
Packit 6c4009
   symbols.
Packit 6c4009
Packit 6c4009
   In practice this often means you will build many short symbols and a
Packit 6c4009
   few long symbols.  At the time you are reading a symbol you don't know
Packit 6c4009
   how long it is.  One traditional method is to read a symbol into a
Packit 6c4009
   buffer, realloc()ating the buffer every time you try to read a symbol
Packit 6c4009
   that is longer than the buffer.  This is beaut, but you still will
Packit 6c4009
   want to copy the symbol from the buffer to a more permanent
Packit 6c4009
   symbol-table entry say about half the time.
Packit 6c4009
Packit 6c4009
   With obstacks, you can work differently.  Use one obstack for all symbol
Packit 6c4009
   names.  As you read a symbol, grow the name in the obstack gradually.
Packit 6c4009
   When the name is complete, finalize it.  Then, if the symbol exists already,
Packit 6c4009
   free the newly read name.
Packit 6c4009
Packit 6c4009
   The way we do this is to take a large chunk, allocating memory from
Packit 6c4009
   low addresses.  When you want to build a symbol in the chunk you just
Packit 6c4009
   add chars above the current "high water mark" in the chunk.  When you
Packit 6c4009
   have finished adding chars, because you got to the end of the symbol,
Packit 6c4009
   you know how long the chars are, and you can create a new object.
Packit 6c4009
   Mostly the chars will not burst over the highest address of the chunk,
Packit 6c4009
   because you would typically expect a chunk to be (say) 100 times as
Packit 6c4009
   long as an average object.
Packit 6c4009
Packit 6c4009
   In case that isn't clear, when we have enough chars to make up
Packit 6c4009
   the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed)
Packit 6c4009
   so we just point to it where it lies.  No moving of chars is
Packit 6c4009
   needed and this is the second win: potentially long strings need
Packit 6c4009
   never be explicitly shuffled. Once an object is formed, it does not
Packit 6c4009
   change its address during its lifetime.
Packit 6c4009
Packit 6c4009
   When the chars burst over a chunk boundary, we allocate a larger
Packit 6c4009
   chunk, and then copy the partly formed object from the end of the old
Packit 6c4009
   chunk to the beginning of the new larger chunk.  We then carry on
Packit 6c4009
   accreting characters to the end of the object as we normally would.
Packit 6c4009
Packit 6c4009
   A special macro is provided to add a single char at a time to a
Packit 6c4009
   growing object.  This allows the use of register variables, which
Packit 6c4009
   break the ordinary 'growth' macro.
Packit 6c4009
Packit 6c4009
   Summary:
Packit 6c4009
	We allocate large chunks.
Packit 6c4009
	We carve out one object at a time from the current chunk.
Packit 6c4009
	Once carved, an object never moves.
Packit 6c4009
	We are free to append data of any size to the currently
Packit 6c4009
	  growing object.
Packit 6c4009
	Exactly one object is growing in an obstack at any one time.
Packit 6c4009
	You can run one obstack per control block.
Packit 6c4009
	You may have as many control blocks as you dare.
Packit 6c4009
	Because of the way we do it, you can "unwind" an obstack
Packit 6c4009
	  back to a previous state. (You may remove objects much
Packit 6c4009
	  as you would with a stack.)
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Don't do the contents of this file more than once.  */
Packit 6c4009
Packit 6c4009
#ifndef _OBSTACK_H
Packit 6c4009
#define _OBSTACK_H 1
Packit 6c4009
Packit 6c4009
/* We need the type of a pointer subtraction.  If __PTRDIFF_TYPE__ is
Packit 6c4009
   defined, as with GNU C, use that; that way we don't pollute the
Packit 6c4009
   namespace with <stddef.h>'s symbols.  Otherwise, include <stddef.h>
Packit 6c4009
   and use ptrdiff_t.  */
Packit 6c4009
Packit 6c4009
#ifdef __PTRDIFF_TYPE__
Packit 6c4009
# define PTR_INT_TYPE __PTRDIFF_TYPE__
Packit 6c4009
#else
Packit 6c4009
# include <stddef.h>
Packit 6c4009
# define PTR_INT_TYPE ptrdiff_t
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
/* If B is the base of an object addressed by P, return the result of
Packit 6c4009
   aligning P to the next multiple of A + 1.  B and P must be of type
Packit 6c4009
   char *.  A + 1 must be a power of 2.  */
Packit 6c4009
Packit 6c4009
#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A)))
Packit 6c4009
Packit 6c4009
/* Similar to _BPTR_ALIGN (B, P, A), except optimize the common case
Packit 6c4009
   where pointers can be converted to integers, aligned as integers,
Packit 6c4009
   and converted back again.  If PTR_INT_TYPE is narrower than a
Packit 6c4009
   pointer (e.g., the AS/400), play it safe and compute the alignment
Packit 6c4009
   relative to B.  Otherwise, use the faster strategy of computing the
Packit 6c4009
   alignment relative to 0.  */
Packit 6c4009
Packit 6c4009
#define __PTR_ALIGN(B, P, A)						      \
Packit 6c4009
  __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \
Packit 6c4009
		P, A)
Packit 6c4009
Packit 6c4009
#include <string.h>
Packit 6c4009
Packit 6c4009
#ifndef __attribute_pure__
Packit 6c4009
# define __attribute_pure__ _GL_ATTRIBUTE_PURE
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#ifdef __cplusplus
Packit 6c4009
extern "C" {
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
struct _obstack_chunk           /* Lives at front of each chunk. */
Packit 6c4009
{
Packit 6c4009
  char *limit;                  /* 1 past end of this chunk */
Packit 6c4009
  struct _obstack_chunk *prev;  /* address of prior chunk or NULL */
Packit 6c4009
  char contents[4];             /* objects begin here */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
struct obstack          /* control current object in current chunk */
Packit 6c4009
{
Packit 6c4009
  long chunk_size;              /* preferred size to allocate chunks in */
Packit 6c4009
  struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */
Packit 6c4009
  char *object_base;            /* address of object we are building */
Packit 6c4009
  char *next_free;              /* where to add next char to current object */
Packit 6c4009
  char *chunk_limit;            /* address of char after current chunk */
Packit 6c4009
  union
Packit 6c4009
  {
Packit 6c4009
    PTR_INT_TYPE tempint;
Packit 6c4009
    void *tempptr;
Packit 6c4009
  } temp;                       /* Temporary for some macros.  */
Packit 6c4009
  int alignment_mask;           /* Mask of alignment for each object. */
Packit 6c4009
  /* These prototypes vary based on 'use_extra_arg', and we use
Packit 6c4009
     casts to the prototypeless function type in all assignments,
Packit 6c4009
     but having prototypes here quiets -Wstrict-prototypes.  */
Packit 6c4009
  struct _obstack_chunk *(*chunkfun) (void *, long);
Packit 6c4009
  void (*freefun) (void *, struct _obstack_chunk *);
Packit 6c4009
  void *extra_arg;              /* first arg for chunk alloc/dealloc funcs */
Packit 6c4009
  unsigned use_extra_arg : 1;     /* chunk alloc/dealloc funcs take extra arg */
Packit 6c4009
  unsigned maybe_empty_object : 1; /* There is a possibility that the current
Packit 6c4009
				      chunk contains a zero-length object.  This
Packit 6c4009
				      prevents freeing the chunk if we allocate
Packit 6c4009
				      a bigger chunk to replace it. */
Packit 6c4009
  unsigned alloc_failed : 1;      /* No longer used, as we now call the failed
Packit 6c4009
				     handler on error, but retained for binary
Packit 6c4009
				     compatibility.  */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Declare the external functions we use; they are in obstack.c.  */
Packit 6c4009
Packit 6c4009
extern void _obstack_newchunk (struct obstack *, int);
Packit 6c4009
extern int _obstack_begin (struct obstack *, int, int,
Packit 6c4009
			   void *(*)(long), void (*)(void *));
Packit 6c4009
extern int _obstack_begin_1 (struct obstack *, int, int,
Packit 6c4009
			     void *(*)(void *, long),
Packit 6c4009
			     void (*)(void *, void *), void *);
Packit 6c4009
extern int _obstack_memory_used (struct obstack *) __attribute_pure__;
Packit 6c4009
Packit 6c4009
/* The default name of the function for freeing a chunk is 'obstack_free',
Packit 6c4009
   but gnulib users can override this by defining '__obstack_free'.  */
Packit 6c4009
#ifndef __obstack_free
Packit 6c4009
# define __obstack_free obstack_free
Packit 6c4009
#endif
Packit 6c4009
extern void __obstack_free (struct obstack *, void *);
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Error handler called when 'obstack_chunk_alloc' failed to allocate
Packit 6c4009
   more memory.  This can be set to a user defined function which
Packit 6c4009
   should either abort gracefully or use longjump - but shouldn't
Packit 6c4009
   return.  The default action is to print a message and abort.  */
Packit 6c4009
extern void (*obstack_alloc_failed_handler) (void);
Packit 6c4009
Packit 6c4009
/* Exit value used when 'print_and_abort' is used.  */
Packit 6c4009
extern int obstack_exit_failure;
Packit 6c4009
Packit 6c4009
/* Pointer to beginning of object being allocated or to be allocated next.
Packit 6c4009
   Note that this might not be the final address of the object
Packit 6c4009
   because a new chunk might be needed to hold the final size.  */
Packit 6c4009
Packit 6c4009
#define obstack_base(h) ((void *) (h)->object_base)
Packit 6c4009
Packit 6c4009
/* Size for allocating ordinary chunks.  */
Packit 6c4009
Packit 6c4009
#define obstack_chunk_size(h) ((h)->chunk_size)
Packit 6c4009
Packit 6c4009
/* Pointer to next byte not yet allocated in current chunk.  */
Packit 6c4009
Packit 6c4009
#define obstack_next_free(h)    ((h)->next_free)
Packit 6c4009
Packit 6c4009
/* Mask specifying low bits that should be clear in address of an object.  */
Packit 6c4009
Packit 6c4009
#define obstack_alignment_mask(h) ((h)->alignment_mask)
Packit 6c4009
Packit 6c4009
/* To prevent prototype warnings provide complete argument list.  */
Packit 6c4009
#define obstack_init(h)							      \
Packit 6c4009
  _obstack_begin ((h), 0, 0,						      \
Packit 6c4009
		  (void *(*)(long))obstack_chunk_alloc,			      \
Packit 6c4009
		  (void (*)(void *))obstack_chunk_free)
Packit 6c4009
Packit 6c4009
#define obstack_begin(h, size)						      \
Packit 6c4009
  _obstack_begin ((h), (size), 0,					      \
Packit 6c4009
		  (void *(*)(long))obstack_chunk_alloc,			      \
Packit 6c4009
		  (void (*)(void *))obstack_chunk_free)
Packit 6c4009
Packit 6c4009
#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun)  \
Packit 6c4009
  _obstack_begin ((h), (size), (alignment),				      \
Packit 6c4009
		  (void *(*)(long))(chunkfun),				      \
Packit 6c4009
		  (void (*)(void *))(freefun))
Packit 6c4009
Packit 6c4009
#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \
Packit 6c4009
  _obstack_begin_1 ((h), (size), (alignment),				      \
Packit 6c4009
		    (void *(*)(void *, long))(chunkfun),		      \
Packit 6c4009
		    (void (*)(void *, void *))(freefun), (arg))
Packit 6c4009
Packit 6c4009
#define obstack_chunkfun(h, newchunkfun) \
Packit 6c4009
  ((h)->chunkfun = (struct _obstack_chunk *(*)(void *, long))(newchunkfun))
Packit 6c4009
Packit 6c4009
#define obstack_freefun(h, newfreefun) \
Packit 6c4009
  ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun))
Packit 6c4009
Packit 6c4009
#define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar))
Packit 6c4009
Packit 6c4009
#define obstack_blank_fast(h, n) ((h)->next_free += (n))
Packit 6c4009
Packit 6c4009
#define obstack_memory_used(h) _obstack_memory_used (h)
Packit 6c4009
Packit 6c4009
#if defined __GNUC__
Packit 6c4009
# if ! (2 < __GNUC__ + (8 <= __GNUC_MINOR__))
Packit 6c4009
#  define __extension__
Packit 6c4009
# endif
Packit 6c4009
Packit 6c4009
/* For GNU C, if not -traditional,
Packit 6c4009
   we can define these macros to compute all args only once
Packit 6c4009
   without using a global variable.
Packit 6c4009
   Also, we can avoid using the 'temp' slot, to make faster code.  */
Packit 6c4009
Packit 6c4009
# define obstack_object_size(OBSTACK)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack const *__o = (OBSTACK);				      \
Packit 6c4009
       (unsigned) (__o->next_free - __o->object_base); })
Packit 6c4009
Packit 6c4009
# define obstack_room(OBSTACK)						      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack const *__o = (OBSTACK);				      \
Packit 6c4009
       (unsigned) (__o->chunk_limit - __o->next_free); })
Packit 6c4009
Packit 6c4009
# define obstack_make_room(OBSTACK, length)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       int __len = (length);						      \
Packit 6c4009
       if (__o->chunk_limit - __o->next_free < __len)			      \
Packit 6c4009
	 _obstack_newchunk (__o, __len);				      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_empty_p(OBSTACK)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack const *__o = (OBSTACK);				      \
Packit 6c4009
       (__o->chunk->prev == 0						      \
Packit 6c4009
	&& __o->next_free == __PTR_ALIGN ((char *) __o->chunk,		      \
Packit 6c4009
					  __o->chunk->contents,		      \
Packit 6c4009
					  __o->alignment_mask)); })
Packit 6c4009
Packit 6c4009
# define obstack_grow(OBSTACK, where, length)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       int __len = (length);						      \
Packit 6c4009
       if (__o->next_free + __len > __o->chunk_limit)			      \
Packit 6c4009
	 _obstack_newchunk (__o, __len);				      \
Packit 6c4009
       memcpy (__o->next_free, where, __len);				      \
Packit 6c4009
       __o->next_free += __len;						      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_grow0(OBSTACK, where, length)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       int __len = (length);						      \
Packit 6c4009
       if (__o->next_free + __len + 1 > __o->chunk_limit)		      \
Packit 6c4009
	 _obstack_newchunk (__o, __len + 1);				      \
Packit 6c4009
       memcpy (__o->next_free, where, __len);				      \
Packit 6c4009
       __o->next_free += __len;						      \
Packit 6c4009
       *(__o->next_free)++ = 0;						      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_1grow(OBSTACK, datum)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       if (__o->next_free + 1 > __o->chunk_limit)			      \
Packit 6c4009
	 _obstack_newchunk (__o, 1);					      \
Packit 6c4009
       obstack_1grow_fast (__o, datum);					      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
/* These assume that the obstack alignment is good enough for pointers
Packit 6c4009
   or ints, and that the data added so far to the current object
Packit 6c4009
   shares that much alignment.  */
Packit 6c4009
Packit 6c4009
# define obstack_ptr_grow(OBSTACK, datum)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       if (__o->next_free + sizeof (void *) > __o->chunk_limit)		      \
Packit 6c4009
	 _obstack_newchunk (__o, sizeof (void *));			      \
Packit 6c4009
       obstack_ptr_grow_fast (__o, datum); })				      \
Packit 6c4009
Packit 6c4009
# define obstack_int_grow(OBSTACK, datum)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       if (__o->next_free + sizeof (int) > __o->chunk_limit)		      \
Packit 6c4009
	 _obstack_newchunk (__o, sizeof (int));				      \
Packit 6c4009
       obstack_int_grow_fast (__o, datum); })
Packit 6c4009
Packit 6c4009
# define obstack_ptr_grow_fast(OBSTACK, aptr)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o1 = (OBSTACK);				      \
Packit 6c4009
       void *__p1 = __o1->next_free;					      \
Packit 6c4009
       *(const void **) __p1 = (aptr);					      \
Packit 6c4009
       __o1->next_free += sizeof (const void *);			      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_int_grow_fast(OBSTACK, aint)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o1 = (OBSTACK);				      \
Packit 6c4009
       void *__p1 = __o1->next_free;					      \
Packit 6c4009
       *(int *) __p1 = (aint);						      \
Packit 6c4009
       __o1->next_free += sizeof (int);					      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_blank(OBSTACK, length)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       int __len = (length);						      \
Packit 6c4009
       if (__o->chunk_limit - __o->next_free < __len)			      \
Packit 6c4009
	 _obstack_newchunk (__o, __len);				      \
Packit 6c4009
       obstack_blank_fast (__o, __len);					      \
Packit 6c4009
       (void) 0; })
Packit 6c4009
Packit 6c4009
# define obstack_alloc(OBSTACK, length)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__h = (OBSTACK);					      \
Packit 6c4009
       obstack_blank (__h, (length));					      \
Packit 6c4009
       obstack_finish (__h); })
Packit 6c4009
Packit 6c4009
# define obstack_copy(OBSTACK, where, length)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__h = (OBSTACK);					      \
Packit 6c4009
       obstack_grow (__h, (where), (length));				      \
Packit 6c4009
       obstack_finish (__h); })
Packit 6c4009
Packit 6c4009
# define obstack_copy0(OBSTACK, where, length)				      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__h = (OBSTACK);					      \
Packit 6c4009
       obstack_grow0 (__h, (where), (length));				      \
Packit 6c4009
       obstack_finish (__h); })
Packit 6c4009
Packit 6c4009
/* The local variable is named __o1 to avoid a name conflict
Packit 6c4009
   when obstack_blank is called.  */
Packit 6c4009
# define obstack_finish(OBSTACK)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o1 = (OBSTACK);				      \
Packit 6c4009
       void *__value = (void *) __o1->object_base;			      \
Packit 6c4009
       if (__o1->next_free == __value)					      \
Packit 6c4009
	 __o1->maybe_empty_object = 1;					      \
Packit 6c4009
       __o1->next_free							      \
Packit 6c4009
	 = __PTR_ALIGN (__o1->object_base, __o1->next_free,		      \
Packit 6c4009
			__o1->alignment_mask);				      \
Packit 6c4009
       if (__o1->next_free - (char *) __o1->chunk			      \
Packit 6c4009
	   > __o1->chunk_limit - (char *) __o1->chunk)			      \
Packit 6c4009
	 __o1->next_free = __o1->chunk_limit;				      \
Packit 6c4009
       __o1->object_base = __o1->next_free;				      \
Packit 6c4009
       __value; })
Packit 6c4009
Packit 6c4009
# define obstack_free(OBSTACK, OBJ)					      \
Packit 6c4009
  __extension__								      \
Packit 6c4009
    ({ struct obstack *__o = (OBSTACK);					      \
Packit 6c4009
       void *__obj = (OBJ);						      \
Packit 6c4009
       if (__obj > (void *) __o->chunk && __obj < (void *) __o->chunk_limit)  \
Packit 6c4009
	 __o->next_free = __o->object_base = (char *) __obj;		      \
Packit 6c4009
       else (__obstack_free) (__o, __obj); })
Packit 6c4009
Packit 6c4009
#else /* not __GNUC__ */
Packit 6c4009
Packit 6c4009
# define obstack_object_size(h) \
Packit 6c4009
  (unsigned) ((h)->next_free - (h)->object_base)
Packit 6c4009
Packit 6c4009
# define obstack_room(h)						      \
Packit 6c4009
  (unsigned) ((h)->chunk_limit - (h)->next_free)
Packit 6c4009
Packit 6c4009
# define obstack_empty_p(h) \
Packit 6c4009
  ((h)->chunk->prev == 0						      \
Packit 6c4009
   && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk,		      \
Packit 6c4009
				     (h)->chunk->contents,		      \
Packit 6c4009
				     (h)->alignment_mask))
Packit 6c4009
Packit 6c4009
/* Note that the call to _obstack_newchunk is enclosed in (..., 0)
Packit 6c4009
   so that we can avoid having void expressions
Packit 6c4009
   in the arms of the conditional expression.
Packit 6c4009
   Casting the third operand to void was tried before,
Packit 6c4009
   but some compilers won't accept it.  */
Packit 6c4009
Packit 6c4009
# define obstack_make_room(h, length)					      \
Packit 6c4009
  ((h)->temp.tempint = (length),					      \
Packit 6c4009
   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		      \
Packit 6c4009
   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0))
Packit 6c4009
Packit 6c4009
# define obstack_grow(h, where, length)					      \
Packit 6c4009
  ((h)->temp.tempint = (length),					      \
Packit 6c4009
   (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit)		      \
Packit 6c4009
   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		      \
Packit 6c4009
   memcpy ((h)->next_free, where, (h)->temp.tempint),			      \
Packit 6c4009
   (h)->next_free += (h)->temp.tempint)
Packit 6c4009
Packit 6c4009
# define obstack_grow0(h, where, length)				      \
Packit 6c4009
  ((h)->temp.tempint = (length),					      \
Packit 6c4009
   (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit)		      \
Packit 6c4009
   ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0),		      \
Packit 6c4009
   memcpy ((h)->next_free, where, (h)->temp.tempint),			      \
Packit 6c4009
   (h)->next_free += (h)->temp.tempint,					      \
Packit 6c4009
   *((h)->next_free)++ = 0)
Packit 6c4009
Packit 6c4009
# define obstack_1grow(h, datum)					      \
Packit 6c4009
  ((((h)->next_free + 1 > (h)->chunk_limit)				      \
Packit 6c4009
    ? (_obstack_newchunk ((h), 1), 0) : 0),				      \
Packit 6c4009
   obstack_1grow_fast (h, datum))
Packit 6c4009
Packit 6c4009
# define obstack_ptr_grow(h, datum)					      \
Packit 6c4009
  ((((h)->next_free + sizeof (char *) > (h)->chunk_limit)		      \
Packit 6c4009
    ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0),		      \
Packit 6c4009
   obstack_ptr_grow_fast (h, datum))
Packit 6c4009
Packit 6c4009
# define obstack_int_grow(h, datum)					      \
Packit 6c4009
  ((((h)->next_free + sizeof (int) > (h)->chunk_limit)			      \
Packit 6c4009
    ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0),			      \
Packit 6c4009
   obstack_int_grow_fast (h, datum))
Packit 6c4009
Packit 6c4009
# define obstack_ptr_grow_fast(h, aptr)					      \
Packit 6c4009
  (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr))
Packit 6c4009
Packit 6c4009
# define obstack_int_grow_fast(h, aint)					      \
Packit 6c4009
  (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint))
Packit 6c4009
Packit 6c4009
# define obstack_blank(h, length)					      \
Packit 6c4009
  ((h)->temp.tempint = (length),					      \
Packit 6c4009
   (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint)		      \
Packit 6c4009
   ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0),		      \
Packit 6c4009
   obstack_blank_fast (h, (h)->temp.tempint))
Packit 6c4009
Packit 6c4009
# define obstack_alloc(h, length)					      \
Packit 6c4009
  (obstack_blank ((h), (length)), obstack_finish ((h)))
Packit 6c4009
Packit 6c4009
# define obstack_copy(h, where, length)					      \
Packit 6c4009
  (obstack_grow ((h), (where), (length)), obstack_finish ((h)))
Packit 6c4009
Packit 6c4009
# define obstack_copy0(h, where, length)				      \
Packit 6c4009
  (obstack_grow0 ((h), (where), (length)), obstack_finish ((h)))
Packit 6c4009
Packit 6c4009
# define obstack_finish(h)						      \
Packit 6c4009
  (((h)->next_free == (h)->object_base					      \
Packit 6c4009
    ? (((h)->maybe_empty_object = 1), 0)				      \
Packit 6c4009
    : 0),								      \
Packit 6c4009
   (h)->temp.tempptr = (h)->object_base,				      \
Packit 6c4009
   (h)->next_free							      \
Packit 6c4009
     = __PTR_ALIGN ((h)->object_base, (h)->next_free,			      \
Packit 6c4009
		    (h)->alignment_mask),				      \
Packit 6c4009
   (((h)->next_free - (char *) (h)->chunk				      \
Packit 6c4009
     > (h)->chunk_limit - (char *) (h)->chunk)				      \
Packit 6c4009
   ? ((h)->next_free = (h)->chunk_limit) : 0),				      \
Packit 6c4009
   (h)->object_base = (h)->next_free,					      \
Packit 6c4009
   (h)->temp.tempptr)
Packit 6c4009
Packit 6c4009
# define obstack_free(h, obj)						      \
Packit 6c4009
  ((h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk,		      \
Packit 6c4009
   ((((h)->temp.tempint > 0						      \
Packit 6c4009
      && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk))	      \
Packit 6c4009
    ? (void) ((h)->next_free = (h)->object_base				      \
Packit 6c4009
	      = (h)->temp.tempint + (char *) (h)->chunk)		      \
Packit 6c4009
    : (__obstack_free) (h, (h)->temp.tempint + (char *) (h)->chunk)))
Packit 6c4009
Packit 6c4009
#endif /* not __GNUC__ */
Packit 6c4009
Packit 6c4009
#ifdef __cplusplus
Packit 6c4009
}       /* C++ */
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
#endif /* obstack.h */