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