133965Sjdp/* objalloc.h -- routines to allocate memory for objects
289857Sobrien   Copyright 1997, 2001 Free Software Foundation, Inc.
333965Sjdp   Written by Ian Lance Taylor, Cygnus Solutions.
433965Sjdp
533965SjdpThis program is free software; you can redistribute it and/or modify it
633965Sjdpunder the terms of the GNU General Public License as published by the
733965SjdpFree Software Foundation; either version 2, or (at your option) any
833965Sjdplater version.
933965Sjdp
1033965SjdpThis program is distributed in the hope that it will be useful,
1133965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1233965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1333965SjdpGNU General Public License for more details.
1433965Sjdp
1533965SjdpYou should have received a copy of the GNU General Public License
1633965Sjdpalong with this program; if not, write to the Free Software
17218822SdimFoundation, 51 Franklin Street - Fifth Floor,
18218822SdimBoston, MA 02110-1301, USA.  */
1933965Sjdp
2033965Sjdp#ifndef OBJALLOC_H
2133965Sjdp#define OBJALLOC_H
2233965Sjdp
2333965Sjdp#include "ansidecl.h"
2433965Sjdp
2533965Sjdp/* These routines allocate space for an object.  The assumption is
2633965Sjdp   that the object will want to allocate space as it goes along, but
2733965Sjdp   will never want to free any particular block.  There is a function
2833965Sjdp   to free a block, which also frees all more recently allocated
2933965Sjdp   blocks.  There is also a function to free all the allocated space.
3033965Sjdp
3133965Sjdp   This is essentially a specialization of obstacks.  The main
3233965Sjdp   difference is that a block may not be allocated a bit at a time.
3333965Sjdp   Another difference is that these routines are always built on top
3433965Sjdp   of malloc, and always pass an malloc failure back to the caller,
3533965Sjdp   unlike more recent versions of obstacks.  */
3633965Sjdp
3733965Sjdp/* This is what an objalloc structure looks like.  Callers should not
3833965Sjdp   refer to these fields, nor should they allocate these structure
3933965Sjdp   themselves.  Instead, they should only create them via
4033965Sjdp   objalloc_init, and only access them via the functions and macros
4133965Sjdp   listed below.  The structure is only defined here so that we can
4233965Sjdp   access it via macros.  */
4333965Sjdp
4433965Sjdpstruct objalloc
4533965Sjdp{
4633965Sjdp  char *current_ptr;
4733965Sjdp  unsigned int current_space;
48218822Sdim  void *chunks;
4933965Sjdp};
5033965Sjdp
5133965Sjdp/* Work out the required alignment.  */
5233965Sjdp
5333965Sjdpstruct objalloc_align { char x; double d; };
5433965Sjdp
5533965Sjdp#if defined (__STDC__) && __STDC__
5633965Sjdp#ifndef offsetof
5733965Sjdp#include <stddef.h>
5833965Sjdp#endif
5933965Sjdp#endif
6089857Sobrien#ifndef offsetof
6189857Sobrien#define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
6289857Sobrien#endif
6389857Sobrien#define OBJALLOC_ALIGN offsetof (struct objalloc_align, d)
6433965Sjdp
6533965Sjdp/* Create an objalloc structure.  Returns NULL if malloc fails.  */
6633965Sjdp
67218822Sdimextern struct objalloc *objalloc_create (void);
6833965Sjdp
6933965Sjdp/* Allocate space from an objalloc structure.  Returns NULL if malloc
7033965Sjdp   fails.  */
7133965Sjdp
72218822Sdimextern void *_objalloc_alloc (struct objalloc *, unsigned long);
7333965Sjdp
7433965Sjdp/* The macro version of objalloc_alloc.  We only define this if using
7533965Sjdp   gcc, because otherwise we would have to evaluate the arguments
7633965Sjdp   multiple times, or use a temporary field as obstack.h does.  */
7733965Sjdp
7833965Sjdp#if defined (__GNUC__) && defined (__STDC__) && __STDC__
7933965Sjdp
8033965Sjdp/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and
8133965Sjdp   does not implement __extension__.  But that compiler doesn't define
8233965Sjdp   __GNUC_MINOR__.  */
8333965Sjdp#if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__)
8433965Sjdp#define __extension__
8533965Sjdp#endif
8633965Sjdp
8733965Sjdp#define objalloc_alloc(o, l)						\
8833965Sjdp  __extension__								\
8933965Sjdp  ({ struct objalloc *__o = (o);					\
9033965Sjdp     unsigned long __len = (l);						\
9133965Sjdp     if (__len == 0)							\
9233965Sjdp       __len = 1;							\
9333965Sjdp     __len = (__len + OBJALLOC_ALIGN - 1) &~ (OBJALLOC_ALIGN - 1);	\
9433965Sjdp     (__len <= __o->current_space					\
9533965Sjdp      ? (__o->current_ptr += __len,					\
9633965Sjdp	 __o->current_space -= __len,					\
97218822Sdim	 (void *) (__o->current_ptr - __len))				\
9833965Sjdp      : _objalloc_alloc (__o, __len)); })
9933965Sjdp
10033965Sjdp#else /* ! __GNUC__ */
10133965Sjdp
10233965Sjdp#define objalloc_alloc(o, l) _objalloc_alloc ((o), (l))
10333965Sjdp
10433965Sjdp#endif /* ! __GNUC__ */
10533965Sjdp
10633965Sjdp/* Free an entire objalloc structure.  */
10733965Sjdp
108218822Sdimextern void objalloc_free (struct objalloc *);
10933965Sjdp
11033965Sjdp/* Free a block allocated by objalloc_alloc.  This also frees all more
11133965Sjdp   recently allocated blocks.  */
11233965Sjdp
113218822Sdimextern void objalloc_free_block (struct objalloc *, void *);
11433965Sjdp
11533965Sjdp#endif /* OBJALLOC_H */
116