xref: /dflybsd-src/contrib/gdb-7/libiberty/obstack.c (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* obstack.c - subroutines used implicitly by object stack macros
286d7f5d3SJohn Marino    Copyright (C) 1988,89,90,91,92,93,94,96,97 Free Software Foundation, Inc.
386d7f5d3SJohn Marino 
486d7f5d3SJohn Marino 
586d7f5d3SJohn Marino    NOTE: This source is derived from an old version taken from the GNU C
686d7f5d3SJohn Marino    Library (glibc).
786d7f5d3SJohn Marino 
886d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify it
986d7f5d3SJohn Marino    under the terms of the GNU General Public License as published by the
1086d7f5d3SJohn Marino    Free Software Foundation; either version 2, or (at your option) any
1186d7f5d3SJohn Marino    later version.
1286d7f5d3SJohn Marino 
1386d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
1486d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
1586d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1686d7f5d3SJohn Marino    GNU General Public License for more details.
1786d7f5d3SJohn Marino 
1886d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
1986d7f5d3SJohn Marino    along with this program; if not, write to the Free Software
2086d7f5d3SJohn Marino    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301,
2186d7f5d3SJohn Marino    USA.  */
2286d7f5d3SJohn Marino 
2386d7f5d3SJohn Marino #ifdef HAVE_CONFIG_H
2486d7f5d3SJohn Marino #include <config.h>
2586d7f5d3SJohn Marino #endif
2686d7f5d3SJohn Marino 
2786d7f5d3SJohn Marino #include "obstack.h"
2886d7f5d3SJohn Marino 
2986d7f5d3SJohn Marino /* NOTE BEFORE MODIFYING THIS FILE: This version number must be
3086d7f5d3SJohn Marino    incremented whenever callers compiled using an old obstack.h can no
3186d7f5d3SJohn Marino    longer properly call the functions in this obstack.c.  */
3286d7f5d3SJohn Marino #define OBSTACK_INTERFACE_VERSION 1
3386d7f5d3SJohn Marino 
3486d7f5d3SJohn Marino /* Comment out all this code if we are using the GNU C Library, and are not
3586d7f5d3SJohn Marino    actually compiling the library itself, and the installed library
3686d7f5d3SJohn Marino    supports the same library interface we do.  This code is part of the GNU
3786d7f5d3SJohn Marino    C Library, but also included in many other GNU distributions.  Compiling
3886d7f5d3SJohn Marino    and linking in this code is a waste when using the GNU C library
3986d7f5d3SJohn Marino    (especially if it is a shared library).  Rather than having every GNU
4086d7f5d3SJohn Marino    program understand `configure --with-gnu-libc' and omit the object
4186d7f5d3SJohn Marino    files, it is simpler to just do this in the source for each such file.  */
4286d7f5d3SJohn Marino 
4386d7f5d3SJohn Marino #include <stdio.h>		/* Random thing to get __GNU_LIBRARY__.  */
4486d7f5d3SJohn Marino #if !defined (_LIBC) && defined (__GNU_LIBRARY__) && __GNU_LIBRARY__ > 1
4586d7f5d3SJohn Marino #include <gnu-versions.h>
4686d7f5d3SJohn Marino #if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
4786d7f5d3SJohn Marino #define ELIDE_CODE
4886d7f5d3SJohn Marino #endif
4986d7f5d3SJohn Marino #endif
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino 
5286d7f5d3SJohn Marino #ifndef ELIDE_CODE
5386d7f5d3SJohn Marino 
5486d7f5d3SJohn Marino 
5586d7f5d3SJohn Marino #define POINTER void *
5686d7f5d3SJohn Marino 
5786d7f5d3SJohn Marino /* Determine default alignment.  */
5886d7f5d3SJohn Marino struct fooalign {char x; double d;};
5986d7f5d3SJohn Marino #define DEFAULT_ALIGNMENT  \
6086d7f5d3SJohn Marino   ((PTR_INT_TYPE) ((char *) &((struct fooalign *) 0)->d - (char *) 0))
6186d7f5d3SJohn Marino /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
6286d7f5d3SJohn Marino    But in fact it might be less smart and round addresses to as much as
6386d7f5d3SJohn Marino    DEFAULT_ROUNDING.  So we prepare for it to do that.  */
6486d7f5d3SJohn Marino union fooround {long x; double d;};
6586d7f5d3SJohn Marino #define DEFAULT_ROUNDING (sizeof (union fooround))
6686d7f5d3SJohn Marino 
6786d7f5d3SJohn Marino /* When we copy a long block of data, this is the unit to do it with.
6886d7f5d3SJohn Marino    On some machines, copying successive ints does not work;
6986d7f5d3SJohn Marino    in such a case, redefine COPYING_UNIT to `long' (if that works)
7086d7f5d3SJohn Marino    or `char' as a last resort.  */
7186d7f5d3SJohn Marino #ifndef COPYING_UNIT
7286d7f5d3SJohn Marino #define COPYING_UNIT int
7386d7f5d3SJohn Marino #endif
7486d7f5d3SJohn Marino 
7586d7f5d3SJohn Marino 
7686d7f5d3SJohn Marino /* The functions allocating more room by calling `obstack_chunk_alloc'
7786d7f5d3SJohn Marino    jump to the handler pointed to by `obstack_alloc_failed_handler'.
7886d7f5d3SJohn Marino    This variable by default points to the internal function
7986d7f5d3SJohn Marino    `print_and_abort'.  */
8086d7f5d3SJohn Marino static void print_and_abort (void);
8186d7f5d3SJohn Marino void (*obstack_alloc_failed_handler) (void) = print_and_abort;
8286d7f5d3SJohn Marino 
8386d7f5d3SJohn Marino /* Exit value used when `print_and_abort' is used.  */
8486d7f5d3SJohn Marino #if defined __GNU_LIBRARY__ || defined HAVE_STDLIB_H
8586d7f5d3SJohn Marino #include <stdlib.h>
8686d7f5d3SJohn Marino #endif
8786d7f5d3SJohn Marino #ifndef EXIT_FAILURE
8886d7f5d3SJohn Marino #define EXIT_FAILURE 1
8986d7f5d3SJohn Marino #endif
9086d7f5d3SJohn Marino int obstack_exit_failure = EXIT_FAILURE;
9186d7f5d3SJohn Marino 
9286d7f5d3SJohn Marino /* The non-GNU-C macros copy the obstack into this global variable
9386d7f5d3SJohn Marino    to avoid multiple evaluation.  */
9486d7f5d3SJohn Marino 
9586d7f5d3SJohn Marino struct obstack *_obstack;
9686d7f5d3SJohn Marino 
9786d7f5d3SJohn Marino /* Define a macro that either calls functions with the traditional malloc/free
9886d7f5d3SJohn Marino    calling interface, or calls functions with the mmalloc/mfree interface
9986d7f5d3SJohn Marino    (that adds an extra first argument), based on the state of use_extra_arg.
10086d7f5d3SJohn Marino    For free, do not use ?:, since some compilers, like the MIPS compilers,
10186d7f5d3SJohn Marino    do not allow (expr) ? void : void.  */
10286d7f5d3SJohn Marino 
10386d7f5d3SJohn Marino #if defined (__STDC__) && __STDC__
10486d7f5d3SJohn Marino #define CALL_CHUNKFUN(h, size) \
10586d7f5d3SJohn Marino   (((h) -> use_extra_arg) \
10686d7f5d3SJohn Marino    ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
10786d7f5d3SJohn Marino    : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size)))
10886d7f5d3SJohn Marino 
10986d7f5d3SJohn Marino #define CALL_FREEFUN(h, old_chunk) \
11086d7f5d3SJohn Marino   do { \
11186d7f5d3SJohn Marino     if ((h) -> use_extra_arg) \
11286d7f5d3SJohn Marino       (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
11386d7f5d3SJohn Marino     else \
11486d7f5d3SJohn Marino       (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \
11586d7f5d3SJohn Marino   } while (0)
11686d7f5d3SJohn Marino #else
11786d7f5d3SJohn Marino #define CALL_CHUNKFUN(h, size) \
11886d7f5d3SJohn Marino   (((h) -> use_extra_arg) \
11986d7f5d3SJohn Marino    ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \
12086d7f5d3SJohn Marino    : (*(struct _obstack_chunk *(*) ()) (h)->chunkfun) ((size)))
12186d7f5d3SJohn Marino 
12286d7f5d3SJohn Marino #define CALL_FREEFUN(h, old_chunk) \
12386d7f5d3SJohn Marino   do { \
12486d7f5d3SJohn Marino     if ((h) -> use_extra_arg) \
12586d7f5d3SJohn Marino       (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \
12686d7f5d3SJohn Marino     else \
12786d7f5d3SJohn Marino       (*(void (*) ()) (h)->freefun) ((old_chunk)); \
12886d7f5d3SJohn Marino   } while (0)
12986d7f5d3SJohn Marino #endif
13086d7f5d3SJohn Marino 
13186d7f5d3SJohn Marino 
13286d7f5d3SJohn Marino /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
13386d7f5d3SJohn Marino    Objects start on multiples of ALIGNMENT (0 means use default).
13486d7f5d3SJohn Marino    CHUNKFUN is the function to use to allocate chunks,
13586d7f5d3SJohn Marino    and FREEFUN the function to free them.
13686d7f5d3SJohn Marino 
13786d7f5d3SJohn Marino    Return nonzero if successful, zero if out of memory.
13886d7f5d3SJohn Marino    To recover from an out of memory error,
13986d7f5d3SJohn Marino    free up some memory, then call this again.  */
14086d7f5d3SJohn Marino 
14186d7f5d3SJohn Marino int
_obstack_begin(struct obstack * h,int size,int alignment,POINTER (* chunkfun)(long),void (* freefun)(void *))14286d7f5d3SJohn Marino _obstack_begin (struct obstack *h, int size, int alignment,
14386d7f5d3SJohn Marino                 POINTER (*chunkfun) (long), void (*freefun) (void *))
14486d7f5d3SJohn Marino {
14586d7f5d3SJohn Marino   register struct _obstack_chunk *chunk; /* points to new chunk */
14686d7f5d3SJohn Marino 
14786d7f5d3SJohn Marino   if (alignment == 0)
14886d7f5d3SJohn Marino     alignment = (int) DEFAULT_ALIGNMENT;
14986d7f5d3SJohn Marino   if (size == 0)
15086d7f5d3SJohn Marino     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
15186d7f5d3SJohn Marino     {
15286d7f5d3SJohn Marino       /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
15386d7f5d3SJohn Marino 	 Use the values for range checking, because if range checking is off,
15486d7f5d3SJohn Marino 	 the extra bytes won't be missed terribly, but if range checking is on
15586d7f5d3SJohn Marino 	 and we used a larger request, a whole extra 4096 bytes would be
15686d7f5d3SJohn Marino 	 allocated.
15786d7f5d3SJohn Marino 
15886d7f5d3SJohn Marino 	 These number are irrelevant to the new GNU malloc.  I suspect it is
15986d7f5d3SJohn Marino 	 less sensitive to the size of the request.  */
16086d7f5d3SJohn Marino       int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
16186d7f5d3SJohn Marino 		    + 4 + DEFAULT_ROUNDING - 1)
16286d7f5d3SJohn Marino 		   & ~(DEFAULT_ROUNDING - 1));
16386d7f5d3SJohn Marino       size = 4096 - extra;
16486d7f5d3SJohn Marino     }
16586d7f5d3SJohn Marino 
16686d7f5d3SJohn Marino   h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun;
16786d7f5d3SJohn Marino   h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
16886d7f5d3SJohn Marino   h->chunk_size = size;
16986d7f5d3SJohn Marino   h->alignment_mask = alignment - 1;
17086d7f5d3SJohn Marino   h->use_extra_arg = 0;
17186d7f5d3SJohn Marino 
17286d7f5d3SJohn Marino   chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
17386d7f5d3SJohn Marino   if (!chunk)
17486d7f5d3SJohn Marino     (*obstack_alloc_failed_handler) ();
17586d7f5d3SJohn Marino   h->next_free = h->object_base = chunk->contents;
17686d7f5d3SJohn Marino   h->chunk_limit = chunk->limit
17786d7f5d3SJohn Marino     = (char *) chunk + h->chunk_size;
17886d7f5d3SJohn Marino   chunk->prev = 0;
17986d7f5d3SJohn Marino   /* The initial chunk now contains no empty object.  */
18086d7f5d3SJohn Marino   h->maybe_empty_object = 0;
18186d7f5d3SJohn Marino   h->alloc_failed = 0;
18286d7f5d3SJohn Marino   return 1;
18386d7f5d3SJohn Marino }
18486d7f5d3SJohn Marino 
18586d7f5d3SJohn Marino int
_obstack_begin_1(struct obstack * h,int size,int alignment,POINTER (* chunkfun)(POINTER,long),void (* freefun)(POINTER,POINTER),POINTER arg)18686d7f5d3SJohn Marino _obstack_begin_1 (struct obstack *h, int size, int alignment,
18786d7f5d3SJohn Marino                   POINTER (*chunkfun) (POINTER, long),
18886d7f5d3SJohn Marino                   void (*freefun) (POINTER, POINTER), POINTER arg)
18986d7f5d3SJohn Marino {
19086d7f5d3SJohn Marino   register struct _obstack_chunk *chunk; /* points to new chunk */
19186d7f5d3SJohn Marino 
19286d7f5d3SJohn Marino   if (alignment == 0)
19386d7f5d3SJohn Marino     alignment = (int) DEFAULT_ALIGNMENT;
19486d7f5d3SJohn Marino   if (size == 0)
19586d7f5d3SJohn Marino     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
19686d7f5d3SJohn Marino     {
19786d7f5d3SJohn Marino       /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
19886d7f5d3SJohn Marino 	 Use the values for range checking, because if range checking is off,
19986d7f5d3SJohn Marino 	 the extra bytes won't be missed terribly, but if range checking is on
20086d7f5d3SJohn Marino 	 and we used a larger request, a whole extra 4096 bytes would be
20186d7f5d3SJohn Marino 	 allocated.
20286d7f5d3SJohn Marino 
20386d7f5d3SJohn Marino 	 These number are irrelevant to the new GNU malloc.  I suspect it is
20486d7f5d3SJohn Marino 	 less sensitive to the size of the request.  */
20586d7f5d3SJohn Marino       int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
20686d7f5d3SJohn Marino 		    + 4 + DEFAULT_ROUNDING - 1)
20786d7f5d3SJohn Marino 		   & ~(DEFAULT_ROUNDING - 1));
20886d7f5d3SJohn Marino       size = 4096 - extra;
20986d7f5d3SJohn Marino     }
21086d7f5d3SJohn Marino 
21186d7f5d3SJohn Marino   h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
21286d7f5d3SJohn Marino   h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
21386d7f5d3SJohn Marino   h->chunk_size = size;
21486d7f5d3SJohn Marino   h->alignment_mask = alignment - 1;
21586d7f5d3SJohn Marino   h->extra_arg = arg;
21686d7f5d3SJohn Marino   h->use_extra_arg = 1;
21786d7f5d3SJohn Marino 
21886d7f5d3SJohn Marino   chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size);
21986d7f5d3SJohn Marino   if (!chunk)
22086d7f5d3SJohn Marino     (*obstack_alloc_failed_handler) ();
22186d7f5d3SJohn Marino   h->next_free = h->object_base = chunk->contents;
22286d7f5d3SJohn Marino   h->chunk_limit = chunk->limit
22386d7f5d3SJohn Marino     = (char *) chunk + h->chunk_size;
22486d7f5d3SJohn Marino   chunk->prev = 0;
22586d7f5d3SJohn Marino   /* The initial chunk now contains no empty object.  */
22686d7f5d3SJohn Marino   h->maybe_empty_object = 0;
22786d7f5d3SJohn Marino   h->alloc_failed = 0;
22886d7f5d3SJohn Marino   return 1;
22986d7f5d3SJohn Marino }
23086d7f5d3SJohn Marino 
23186d7f5d3SJohn Marino /* Allocate a new current chunk for the obstack *H
23286d7f5d3SJohn Marino    on the assumption that LENGTH bytes need to be added
23386d7f5d3SJohn Marino    to the current object, or a new object of length LENGTH allocated.
23486d7f5d3SJohn Marino    Copies any partial object from the end of the old chunk
23586d7f5d3SJohn Marino    to the beginning of the new one.  */
23686d7f5d3SJohn Marino 
23786d7f5d3SJohn Marino void
_obstack_newchunk(struct obstack * h,int length)23886d7f5d3SJohn Marino _obstack_newchunk (struct obstack *h, int length)
23986d7f5d3SJohn Marino {
24086d7f5d3SJohn Marino   register struct _obstack_chunk *old_chunk = h->chunk;
24186d7f5d3SJohn Marino   register struct _obstack_chunk *new_chunk;
24286d7f5d3SJohn Marino   register long	new_size;
24386d7f5d3SJohn Marino   register long obj_size = h->next_free - h->object_base;
24486d7f5d3SJohn Marino   register long i;
24586d7f5d3SJohn Marino   long already;
24686d7f5d3SJohn Marino 
24786d7f5d3SJohn Marino   /* Compute size for new chunk.  */
24886d7f5d3SJohn Marino   new_size = (obj_size + length) + (obj_size >> 3) + 100;
24986d7f5d3SJohn Marino   if (new_size < h->chunk_size)
25086d7f5d3SJohn Marino     new_size = h->chunk_size;
25186d7f5d3SJohn Marino 
25286d7f5d3SJohn Marino   /* Allocate and initialize the new chunk.  */
25386d7f5d3SJohn Marino   new_chunk = CALL_CHUNKFUN (h, new_size);
25486d7f5d3SJohn Marino   if (!new_chunk)
25586d7f5d3SJohn Marino     (*obstack_alloc_failed_handler) ();
25686d7f5d3SJohn Marino   h->chunk = new_chunk;
25786d7f5d3SJohn Marino   new_chunk->prev = old_chunk;
25886d7f5d3SJohn Marino   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
25986d7f5d3SJohn Marino 
26086d7f5d3SJohn Marino   /* Move the existing object to the new chunk.
26186d7f5d3SJohn Marino      Word at a time is fast and is safe if the object
26286d7f5d3SJohn Marino      is sufficiently aligned.  */
26386d7f5d3SJohn Marino   if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
26486d7f5d3SJohn Marino     {
26586d7f5d3SJohn Marino       for (i = obj_size / sizeof (COPYING_UNIT) - 1;
26686d7f5d3SJohn Marino 	   i >= 0; i--)
26786d7f5d3SJohn Marino 	((COPYING_UNIT *)new_chunk->contents)[i]
26886d7f5d3SJohn Marino 	  = ((COPYING_UNIT *)h->object_base)[i];
26986d7f5d3SJohn Marino       /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
27086d7f5d3SJohn Marino 	 but that can cross a page boundary on a machine
27186d7f5d3SJohn Marino 	 which does not do strict alignment for COPYING_UNITS.  */
27286d7f5d3SJohn Marino       already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
27386d7f5d3SJohn Marino     }
27486d7f5d3SJohn Marino   else
27586d7f5d3SJohn Marino     already = 0;
27686d7f5d3SJohn Marino   /* Copy remaining bytes one by one.  */
27786d7f5d3SJohn Marino   for (i = already; i < obj_size; i++)
27886d7f5d3SJohn Marino     new_chunk->contents[i] = h->object_base[i];
27986d7f5d3SJohn Marino 
28086d7f5d3SJohn Marino   /* If the object just copied was the only data in OLD_CHUNK,
28186d7f5d3SJohn Marino      free that chunk and remove it from the chain.
28286d7f5d3SJohn Marino      But not if that chunk might contain an empty object.  */
28386d7f5d3SJohn Marino   if (h->object_base == old_chunk->contents && ! h->maybe_empty_object)
28486d7f5d3SJohn Marino     {
28586d7f5d3SJohn Marino       new_chunk->prev = old_chunk->prev;
28686d7f5d3SJohn Marino       CALL_FREEFUN (h, old_chunk);
28786d7f5d3SJohn Marino     }
28886d7f5d3SJohn Marino 
28986d7f5d3SJohn Marino   h->object_base = new_chunk->contents;
29086d7f5d3SJohn Marino   h->next_free = h->object_base + obj_size;
29186d7f5d3SJohn Marino   /* The new chunk certainly contains no empty object yet.  */
29286d7f5d3SJohn Marino   h->maybe_empty_object = 0;
29386d7f5d3SJohn Marino }
29486d7f5d3SJohn Marino 
29586d7f5d3SJohn Marino /* Return nonzero if object OBJ has been allocated from obstack H.
29686d7f5d3SJohn Marino    This is here for debugging.
29786d7f5d3SJohn Marino    If you use it in a program, you are probably losing.  */
29886d7f5d3SJohn Marino 
29986d7f5d3SJohn Marino /* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
30086d7f5d3SJohn Marino    obstack.h because it is just for debugging.  */
30186d7f5d3SJohn Marino int _obstack_allocated_p (struct obstack *h, POINTER obj);
30286d7f5d3SJohn Marino 
30386d7f5d3SJohn Marino int
_obstack_allocated_p(struct obstack * h,POINTER obj)30486d7f5d3SJohn Marino _obstack_allocated_p (struct obstack *h, POINTER obj)
30586d7f5d3SJohn Marino {
30686d7f5d3SJohn Marino   register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
30786d7f5d3SJohn Marino   register struct _obstack_chunk *plp;	/* point to previous chunk if any */
30886d7f5d3SJohn Marino 
30986d7f5d3SJohn Marino   lp = (h)->chunk;
31086d7f5d3SJohn Marino   /* We use >= rather than > since the object cannot be exactly at
31186d7f5d3SJohn Marino      the beginning of the chunk but might be an empty object exactly
31286d7f5d3SJohn Marino      at the end of an adjacent chunk.  */
31386d7f5d3SJohn Marino   while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
31486d7f5d3SJohn Marino     {
31586d7f5d3SJohn Marino       plp = lp->prev;
31686d7f5d3SJohn Marino       lp = plp;
31786d7f5d3SJohn Marino     }
31886d7f5d3SJohn Marino   return lp != 0;
31986d7f5d3SJohn Marino }
32086d7f5d3SJohn Marino 
32186d7f5d3SJohn Marino /* Free objects in obstack H, including OBJ and everything allocate
32286d7f5d3SJohn Marino    more recently than OBJ.  If OBJ is zero, free everything in H.  */
32386d7f5d3SJohn Marino 
32486d7f5d3SJohn Marino #undef obstack_free
32586d7f5d3SJohn Marino 
32686d7f5d3SJohn Marino /* This function has two names with identical definitions.
32786d7f5d3SJohn Marino    This is the first one, called from non-ANSI code.  */
32886d7f5d3SJohn Marino 
32986d7f5d3SJohn Marino void
_obstack_free(struct obstack * h,POINTER obj)33086d7f5d3SJohn Marino _obstack_free (struct obstack *h, POINTER obj)
33186d7f5d3SJohn Marino {
33286d7f5d3SJohn Marino   register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
33386d7f5d3SJohn Marino   register struct _obstack_chunk *plp;	/* point to previous chunk if any */
33486d7f5d3SJohn Marino 
33586d7f5d3SJohn Marino   lp = h->chunk;
33686d7f5d3SJohn Marino   /* We use >= because there cannot be an object at the beginning of a chunk.
33786d7f5d3SJohn Marino      But there can be an empty object at that address
33886d7f5d3SJohn Marino      at the end of another chunk.  */
33986d7f5d3SJohn Marino   while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
34086d7f5d3SJohn Marino     {
34186d7f5d3SJohn Marino       plp = lp->prev;
34286d7f5d3SJohn Marino       CALL_FREEFUN (h, lp);
34386d7f5d3SJohn Marino       lp = plp;
34486d7f5d3SJohn Marino       /* If we switch chunks, we can't tell whether the new current
34586d7f5d3SJohn Marino 	 chunk contains an empty object, so assume that it may.  */
34686d7f5d3SJohn Marino       h->maybe_empty_object = 1;
34786d7f5d3SJohn Marino     }
34886d7f5d3SJohn Marino   if (lp)
34986d7f5d3SJohn Marino     {
35086d7f5d3SJohn Marino       h->object_base = h->next_free = (char *) (obj);
35186d7f5d3SJohn Marino       h->chunk_limit = lp->limit;
35286d7f5d3SJohn Marino       h->chunk = lp;
35386d7f5d3SJohn Marino     }
35486d7f5d3SJohn Marino   else if (obj != 0)
35586d7f5d3SJohn Marino     /* obj is not in any of the chunks! */
35686d7f5d3SJohn Marino     abort ();
35786d7f5d3SJohn Marino }
35886d7f5d3SJohn Marino 
35986d7f5d3SJohn Marino /* This function is used from ANSI code.  */
36086d7f5d3SJohn Marino 
36186d7f5d3SJohn Marino void
obstack_free(struct obstack * h,POINTER obj)36286d7f5d3SJohn Marino obstack_free (struct obstack *h, POINTER obj)
36386d7f5d3SJohn Marino {
36486d7f5d3SJohn Marino   register struct _obstack_chunk *lp;	/* below addr of any objects in this chunk */
36586d7f5d3SJohn Marino   register struct _obstack_chunk *plp;	/* point to previous chunk if any */
36686d7f5d3SJohn Marino 
36786d7f5d3SJohn Marino   lp = h->chunk;
36886d7f5d3SJohn Marino   /* We use >= because there cannot be an object at the beginning of a chunk.
36986d7f5d3SJohn Marino      But there can be an empty object at that address
37086d7f5d3SJohn Marino      at the end of another chunk.  */
37186d7f5d3SJohn Marino   while (lp != 0 && ((POINTER) lp >= obj || (POINTER) (lp)->limit < obj))
37286d7f5d3SJohn Marino     {
37386d7f5d3SJohn Marino       plp = lp->prev;
37486d7f5d3SJohn Marino       CALL_FREEFUN (h, lp);
37586d7f5d3SJohn Marino       lp = plp;
37686d7f5d3SJohn Marino       /* If we switch chunks, we can't tell whether the new current
37786d7f5d3SJohn Marino 	 chunk contains an empty object, so assume that it may.  */
37886d7f5d3SJohn Marino       h->maybe_empty_object = 1;
37986d7f5d3SJohn Marino     }
38086d7f5d3SJohn Marino   if (lp)
38186d7f5d3SJohn Marino     {
38286d7f5d3SJohn Marino       h->object_base = h->next_free = (char *) (obj);
38386d7f5d3SJohn Marino       h->chunk_limit = lp->limit;
38486d7f5d3SJohn Marino       h->chunk = lp;
38586d7f5d3SJohn Marino     }
38686d7f5d3SJohn Marino   else if (obj != 0)
38786d7f5d3SJohn Marino     /* obj is not in any of the chunks! */
38886d7f5d3SJohn Marino     abort ();
38986d7f5d3SJohn Marino }
39086d7f5d3SJohn Marino 
39186d7f5d3SJohn Marino int
_obstack_memory_used(struct obstack * h)39286d7f5d3SJohn Marino _obstack_memory_used (struct obstack *h)
39386d7f5d3SJohn Marino {
39486d7f5d3SJohn Marino   register struct _obstack_chunk* lp;
39586d7f5d3SJohn Marino   register int nbytes = 0;
39686d7f5d3SJohn Marino 
39786d7f5d3SJohn Marino   for (lp = h->chunk; lp != 0; lp = lp->prev)
39886d7f5d3SJohn Marino     {
39986d7f5d3SJohn Marino       nbytes += lp->limit - (char *) lp;
40086d7f5d3SJohn Marino     }
40186d7f5d3SJohn Marino   return nbytes;
40286d7f5d3SJohn Marino }
40386d7f5d3SJohn Marino 
40486d7f5d3SJohn Marino /* Define the error handler.  */
40586d7f5d3SJohn Marino #ifndef _
40686d7f5d3SJohn Marino # if (HAVE_LIBINTL_H && ENABLE_NLS) || defined _LIBC
40786d7f5d3SJohn Marino #  include <libintl.h>
40886d7f5d3SJohn Marino #  ifndef _
40986d7f5d3SJohn Marino #   define _(Str) gettext (Str)
41086d7f5d3SJohn Marino #  endif
41186d7f5d3SJohn Marino # else
41286d7f5d3SJohn Marino #  define _(Str) (Str)
41386d7f5d3SJohn Marino # endif
41486d7f5d3SJohn Marino #endif
41586d7f5d3SJohn Marino 
41686d7f5d3SJohn Marino static void
print_and_abort(void)41786d7f5d3SJohn Marino print_and_abort (void)
41886d7f5d3SJohn Marino {
41986d7f5d3SJohn Marino   fputs (_("memory exhausted\n"), stderr);
42086d7f5d3SJohn Marino   exit (obstack_exit_failure);
42186d7f5d3SJohn Marino }
42286d7f5d3SJohn Marino 
42386d7f5d3SJohn Marino #if 0
42486d7f5d3SJohn Marino /* These are now turned off because the applications do not use it
42586d7f5d3SJohn Marino    and it uses bcopy via obstack_grow, which causes trouble on sysV.  */
42686d7f5d3SJohn Marino 
42786d7f5d3SJohn Marino /* Now define the functional versions of the obstack macros.
42886d7f5d3SJohn Marino    Define them to simply use the corresponding macros to do the job.  */
42986d7f5d3SJohn Marino 
43086d7f5d3SJohn Marino /* The function names appear in parentheses in order to prevent
43186d7f5d3SJohn Marino    the macro-definitions of the names from being expanded there.  */
43286d7f5d3SJohn Marino 
43386d7f5d3SJohn Marino POINTER (obstack_base) (struct obstack *obstack)
43486d7f5d3SJohn Marino {
43586d7f5d3SJohn Marino   return obstack_base (obstack);
43686d7f5d3SJohn Marino }
43786d7f5d3SJohn Marino 
43886d7f5d3SJohn Marino POINTER (obstack_next_free) (struct obstack *obstack)
43986d7f5d3SJohn Marino {
44086d7f5d3SJohn Marino   return obstack_next_free (obstack);
44186d7f5d3SJohn Marino }
44286d7f5d3SJohn Marino 
44386d7f5d3SJohn Marino int (obstack_object_size) (struct obstack *obstack)
44486d7f5d3SJohn Marino {
44586d7f5d3SJohn Marino   return obstack_object_size (obstack);
44686d7f5d3SJohn Marino }
44786d7f5d3SJohn Marino 
44886d7f5d3SJohn Marino int (obstack_room) (struct obstack *obstack)
44986d7f5d3SJohn Marino {
45086d7f5d3SJohn Marino   return obstack_room (obstack);
45186d7f5d3SJohn Marino }
45286d7f5d3SJohn Marino 
45386d7f5d3SJohn Marino int (obstack_make_room) (struct obstack *obstack, int length)
45486d7f5d3SJohn Marino {
45586d7f5d3SJohn Marino   return obstack_make_room (obstack, length);
45686d7f5d3SJohn Marino }
45786d7f5d3SJohn Marino 
45886d7f5d3SJohn Marino void (obstack_grow) (struct obstack *obstack, POINTER pointer, int length)
45986d7f5d3SJohn Marino {
46086d7f5d3SJohn Marino   obstack_grow (obstack, pointer, length);
46186d7f5d3SJohn Marino }
46286d7f5d3SJohn Marino 
46386d7f5d3SJohn Marino void (obstack_grow0) (struct obstack *obstack, POINTER pointer, int length)
46486d7f5d3SJohn Marino {
46586d7f5d3SJohn Marino   obstack_grow0 (obstack, pointer, length);
46686d7f5d3SJohn Marino }
46786d7f5d3SJohn Marino 
46886d7f5d3SJohn Marino void (obstack_1grow) (struct obstack *obstack, int character)
46986d7f5d3SJohn Marino {
47086d7f5d3SJohn Marino   obstack_1grow (obstack, character);
47186d7f5d3SJohn Marino }
47286d7f5d3SJohn Marino 
47386d7f5d3SJohn Marino void (obstack_blank) (struct obstack *obstack, int length)
47486d7f5d3SJohn Marino {
47586d7f5d3SJohn Marino   obstack_blank (obstack, length);
47686d7f5d3SJohn Marino }
47786d7f5d3SJohn Marino 
47886d7f5d3SJohn Marino void (obstack_1grow_fast) (struct obstack *obstack, int character)
47986d7f5d3SJohn Marino {
48086d7f5d3SJohn Marino   obstack_1grow_fast (obstack, character);
48186d7f5d3SJohn Marino }
48286d7f5d3SJohn Marino 
48386d7f5d3SJohn Marino void (obstack_blank_fast) (struct obstack *obstack, int length)
48486d7f5d3SJohn Marino {
48586d7f5d3SJohn Marino   obstack_blank_fast (obstack, length);
48686d7f5d3SJohn Marino }
48786d7f5d3SJohn Marino 
48886d7f5d3SJohn Marino POINTER (obstack_finish) (struct obstack *obstack)
48986d7f5d3SJohn Marino {
49086d7f5d3SJohn Marino   return obstack_finish (obstack);
49186d7f5d3SJohn Marino }
49286d7f5d3SJohn Marino 
49386d7f5d3SJohn Marino POINTER (obstack_alloc) (struct obstack *obstack, int length)
49486d7f5d3SJohn Marino {
49586d7f5d3SJohn Marino   return obstack_alloc (obstack, length);
49686d7f5d3SJohn Marino }
49786d7f5d3SJohn Marino 
49886d7f5d3SJohn Marino POINTER (obstack_copy) (struct obstack *obstack, POINTER pointer, int length)
49986d7f5d3SJohn Marino {
50086d7f5d3SJohn Marino   return obstack_copy (obstack, pointer, length);
50186d7f5d3SJohn Marino }
50286d7f5d3SJohn Marino 
50386d7f5d3SJohn Marino POINTER (obstack_copy0) (struct obstack *obstack, POINTER pointer, int length)
50486d7f5d3SJohn Marino {
50586d7f5d3SJohn Marino   return obstack_copy0 (obstack, pointer, length);
50686d7f5d3SJohn Marino }
50786d7f5d3SJohn Marino 
50886d7f5d3SJohn Marino #endif /* 0 */
50986d7f5d3SJohn Marino 
51086d7f5d3SJohn Marino #endif	/* !ELIDE_CODE */
511