xref: /dflybsd-src/contrib/grep/lib/obstack.c (revision 91b9ed38d3db6a8a8ac5b66da1d43e6e331e259a)
195b7b453SJohn Marino /* obstack.c - subroutines used implicitly by object stack macros
2*09d4459fSDaniel Fojt    Copyright (C) 1988-2020 Free Software Foundation, Inc.
3680a9cb8SJohn Marino    This file is part of the GNU C Library.
495b7b453SJohn Marino 
5680a9cb8SJohn Marino    The GNU C Library is free software; you can redistribute it and/or
6680a9cb8SJohn Marino    modify it under the terms of the GNU General Public
7680a9cb8SJohn Marino    License as published by the Free Software Foundation; either
8680a9cb8SJohn Marino    version 3 of the License, or (at your option) any later version.
995b7b453SJohn Marino 
10680a9cb8SJohn Marino    The GNU C Library is distributed in the hope that it will be useful,
1195b7b453SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
12680a9cb8SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13680a9cb8SJohn Marino    General Public License for more details.
1495b7b453SJohn Marino 
15680a9cb8SJohn Marino    You should have received a copy of the GNU General Public
16680a9cb8SJohn Marino    License along with the GNU C Library; if not, see
17*09d4459fSDaniel Fojt    <https://www.gnu.org/licenses/>.  */
18680a9cb8SJohn Marino 
1995b7b453SJohn Marino 
2095b7b453SJohn Marino #ifdef _LIBC
2195b7b453SJohn Marino # include <obstack.h>
2295b7b453SJohn Marino #else
2395b7b453SJohn Marino # include <config.h>
2495b7b453SJohn Marino # include "obstack.h"
2595b7b453SJohn Marino #endif
2695b7b453SJohn Marino 
27dc7c36e4SJohn Marino /* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
28dc7c36e4SJohn Marino    obstack.h must be incremented whenever callers compiled using an old
29dc7c36e4SJohn Marino    obstack.h can no longer properly call the functions in this file.  */
3095b7b453SJohn Marino 
3195b7b453SJohn Marino /* Comment out all this code if we are using the GNU C Library, and are not
3295b7b453SJohn Marino    actually compiling the library itself, and the installed library
3395b7b453SJohn Marino    supports the same library interface we do.  This code is part of the GNU
3495b7b453SJohn Marino    C Library, but also included in many other GNU distributions.  Compiling
3595b7b453SJohn Marino    and linking in this code is a waste when using the GNU C library
3695b7b453SJohn Marino    (especially if it is a shared library).  Rather than having every GNU
37cf28ed85SJohn Marino    program understand 'configure --with-gnu-libc' and omit the object
3895b7b453SJohn Marino    files, it is simpler to just do this in the source for each such file.  */
3995b7b453SJohn Marino #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
4095b7b453SJohn Marino # include <gnu-versions.h>
41dc7c36e4SJohn Marino # if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION	      \
42dc7c36e4SJohn Marino       || (_GNU_OBSTACK_INTERFACE_VERSION == 1				      \
43dc7c36e4SJohn Marino           && _OBSTACK_INTERFACE_VERSION == 2				      \
44dc7c36e4SJohn Marino           && defined SIZEOF_INT && defined SIZEOF_SIZE_T		      \
45dc7c36e4SJohn Marino           && SIZEOF_INT == SIZEOF_SIZE_T))
46dc7c36e4SJohn Marino #  define _OBSTACK_ELIDE_CODE
4795b7b453SJohn Marino # endif
4895b7b453SJohn Marino #endif
4995b7b453SJohn Marino 
50dc7c36e4SJohn Marino #ifndef _OBSTACK_ELIDE_CODE
51dc7c36e4SJohn Marino /* If GCC, or if an oddball (testing?) host that #defines __alignof__,
52dc7c36e4SJohn Marino    use the already-supplied __alignof__.  Otherwise, this must be Gnulib
53dc7c36e4SJohn Marino    (as glibc assumes GCC); defer to Gnulib's alignof_type.  */
54dc7c36e4SJohn Marino # if !defined __GNUC__ && !defined __alignof__
55dc7c36e4SJohn Marino #  include <alignof.h>
56dc7c36e4SJohn Marino #  define __alignof__(type) alignof_type (type)
57dc7c36e4SJohn Marino # endif
58dc7c36e4SJohn Marino # include <stdlib.h>
5995b7b453SJohn Marino # include <stdint.h>
6095b7b453SJohn Marino 
61dc7c36e4SJohn Marino # ifndef MAX
62dc7c36e4SJohn Marino #  define MAX(a,b) ((a) > (b) ? (a) : (b))
63dc7c36e4SJohn Marino # endif
64dc7c36e4SJohn Marino 
6595b7b453SJohn Marino /* Determine default alignment.  */
66dc7c36e4SJohn Marino 
6795b7b453SJohn Marino /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
6895b7b453SJohn Marino    But in fact it might be less smart and round addresses to as much as
69dc7c36e4SJohn Marino    DEFAULT_ROUNDING.  So we prepare for it to do that.
70dc7c36e4SJohn Marino 
71dc7c36e4SJohn Marino    DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h.  */
72dc7c36e4SJohn Marino #define DEFAULT_ALIGNMENT MAX (__alignof__ (long double),		      \
73dc7c36e4SJohn Marino                                MAX (__alignof__ (uintmax_t),		      \
74dc7c36e4SJohn Marino                                     __alignof__ (void *)))
75dc7c36e4SJohn Marino #define DEFAULT_ROUNDING MAX (sizeof (long double),			      \
76dc7c36e4SJohn Marino                                MAX (sizeof (uintmax_t),			      \
77dc7c36e4SJohn Marino                                     sizeof (void *)))
78dc7c36e4SJohn Marino 
79dc7c36e4SJohn Marino /* Call functions with either the traditional malloc/free calling
80dc7c36e4SJohn Marino    interface, or the mmalloc/mfree interface (that adds an extra first
81dc7c36e4SJohn Marino    argument), based on the value of use_extra_arg.  */
82dc7c36e4SJohn Marino 
83dc7c36e4SJohn Marino static void *
call_chunkfun(struct obstack * h,size_t size)84dc7c36e4SJohn Marino call_chunkfun (struct obstack *h, size_t size)
8595b7b453SJohn Marino {
86dc7c36e4SJohn Marino   if (h->use_extra_arg)
87dc7c36e4SJohn Marino     return h->chunkfun.extra (h->extra_arg, size);
88dc7c36e4SJohn Marino   else
89dc7c36e4SJohn Marino     return h->chunkfun.plain (size);
90dc7c36e4SJohn Marino }
9195b7b453SJohn Marino 
92dc7c36e4SJohn Marino static void
call_freefun(struct obstack * h,void * old_chunk)93dc7c36e4SJohn Marino call_freefun (struct obstack *h, void *old_chunk)
94dc7c36e4SJohn Marino {
95dc7c36e4SJohn Marino   if (h->use_extra_arg)
96dc7c36e4SJohn Marino     h->freefun.extra (h->extra_arg, old_chunk);
97dc7c36e4SJohn Marino   else
98dc7c36e4SJohn Marino     h->freefun.plain (old_chunk);
99dc7c36e4SJohn Marino }
10095b7b453SJohn Marino 
101680a9cb8SJohn Marino 
10295b7b453SJohn Marino /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
10395b7b453SJohn Marino    Objects start on multiples of ALIGNMENT (0 means use default).
10495b7b453SJohn Marino 
10595b7b453SJohn Marino    Return nonzero if successful, calls obstack_alloc_failed_handler if
10695b7b453SJohn Marino    allocation fails.  */
10795b7b453SJohn Marino 
108dc7c36e4SJohn Marino static int
_obstack_begin_worker(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment)109dc7c36e4SJohn Marino _obstack_begin_worker (struct obstack *h,
110dc7c36e4SJohn Marino                        _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment)
11195b7b453SJohn Marino {
112680a9cb8SJohn Marino   struct _obstack_chunk *chunk; /* points to new chunk */
11395b7b453SJohn Marino 
11495b7b453SJohn Marino   if (alignment == 0)
11595b7b453SJohn Marino     alignment = DEFAULT_ALIGNMENT;
11695b7b453SJohn Marino   if (size == 0)
11795b7b453SJohn Marino     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
11895b7b453SJohn Marino     {
11995b7b453SJohn Marino       /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
12095b7b453SJohn Marino          Use the values for range checking, because if range checking is off,
12195b7b453SJohn Marino          the extra bytes won't be missed terribly, but if range checking is on
12295b7b453SJohn Marino          and we used a larger request, a whole extra 4096 bytes would be
12395b7b453SJohn Marino          allocated.
12495b7b453SJohn Marino 
12595b7b453SJohn Marino          These number are irrelevant to the new GNU malloc.  I suspect it is
12695b7b453SJohn Marino          less sensitive to the size of the request.  */
12795b7b453SJohn Marino       int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
12895b7b453SJohn Marino                     + 4 + DEFAULT_ROUNDING - 1)
12995b7b453SJohn Marino                    & ~(DEFAULT_ROUNDING - 1));
13095b7b453SJohn Marino       size = 4096 - extra;
13195b7b453SJohn Marino     }
13295b7b453SJohn Marino 
13395b7b453SJohn Marino   h->chunk_size = size;
13495b7b453SJohn Marino   h->alignment_mask = alignment - 1;
13595b7b453SJohn Marino 
136dc7c36e4SJohn Marino   chunk = h->chunk = call_chunkfun (h, h->chunk_size);
13795b7b453SJohn Marino   if (!chunk)
13895b7b453SJohn Marino     (*obstack_alloc_failed_handler) ();
13995b7b453SJohn Marino   h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
14095b7b453SJohn Marino                                                alignment - 1);
141dc7c36e4SJohn Marino   h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
14295b7b453SJohn Marino   chunk->prev = 0;
14395b7b453SJohn Marino   /* The initial chunk now contains no empty object.  */
14495b7b453SJohn Marino   h->maybe_empty_object = 0;
14595b7b453SJohn Marino   h->alloc_failed = 0;
14695b7b453SJohn Marino   return 1;
14795b7b453SJohn Marino }
14895b7b453SJohn Marino 
14995b7b453SJohn Marino int
_obstack_begin(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment,void * (* chunkfun)(size_t),void (* freefun)(void *))150dc7c36e4SJohn Marino _obstack_begin (struct obstack *h,
151dc7c36e4SJohn Marino                 _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
152dc7c36e4SJohn Marino                 void *(*chunkfun) (size_t),
153dc7c36e4SJohn Marino                 void (*freefun) (void *))
154dc7c36e4SJohn Marino {
155dc7c36e4SJohn Marino   h->chunkfun.plain = chunkfun;
156dc7c36e4SJohn Marino   h->freefun.plain = freefun;
157dc7c36e4SJohn Marino   h->use_extra_arg = 0;
158dc7c36e4SJohn Marino   return _obstack_begin_worker (h, size, alignment);
159dc7c36e4SJohn Marino }
160dc7c36e4SJohn Marino 
161dc7c36e4SJohn Marino int
_obstack_begin_1(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment,void * (* chunkfun)(void *,size_t),void (* freefun)(void *,void *),void * arg)162dc7c36e4SJohn Marino _obstack_begin_1 (struct obstack *h,
163dc7c36e4SJohn Marino                   _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
164dc7c36e4SJohn Marino                   void *(*chunkfun) (void *, size_t),
16595b7b453SJohn Marino                   void (*freefun) (void *, void *),
16695b7b453SJohn Marino                   void *arg)
16795b7b453SJohn Marino {
168dc7c36e4SJohn Marino   h->chunkfun.extra = chunkfun;
169dc7c36e4SJohn Marino   h->freefun.extra = freefun;
17095b7b453SJohn Marino   h->extra_arg = arg;
17195b7b453SJohn Marino   h->use_extra_arg = 1;
172dc7c36e4SJohn Marino   return _obstack_begin_worker (h, size, alignment);
17395b7b453SJohn Marino }
17495b7b453SJohn Marino 
17595b7b453SJohn Marino /* Allocate a new current chunk for the obstack *H
17695b7b453SJohn Marino    on the assumption that LENGTH bytes need to be added
17795b7b453SJohn Marino    to the current object, or a new object of length LENGTH allocated.
17895b7b453SJohn Marino    Copies any partial object from the end of the old chunk
17995b7b453SJohn Marino    to the beginning of the new one.  */
18095b7b453SJohn Marino 
18195b7b453SJohn Marino void
_obstack_newchunk(struct obstack * h,_OBSTACK_SIZE_T length)182dc7c36e4SJohn Marino _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
18395b7b453SJohn Marino {
184680a9cb8SJohn Marino   struct _obstack_chunk *old_chunk = h->chunk;
185dc7c36e4SJohn Marino   struct _obstack_chunk *new_chunk = 0;
186dc7c36e4SJohn Marino   size_t obj_size = h->next_free - h->object_base;
18795b7b453SJohn Marino   char *object_base;
18895b7b453SJohn Marino 
18995b7b453SJohn Marino   /* Compute size for new chunk.  */
190dc7c36e4SJohn Marino   size_t sum1 = obj_size + length;
191dc7c36e4SJohn Marino   size_t sum2 = sum1 + h->alignment_mask;
192dc7c36e4SJohn Marino   size_t new_size = sum2 + (obj_size >> 3) + 100;
193dc7c36e4SJohn Marino   if (new_size < sum2)
194dc7c36e4SJohn Marino     new_size = sum2;
19595b7b453SJohn Marino   if (new_size < h->chunk_size)
19695b7b453SJohn Marino     new_size = h->chunk_size;
19795b7b453SJohn Marino 
19895b7b453SJohn Marino   /* Allocate and initialize the new chunk.  */
199dc7c36e4SJohn Marino   if (obj_size <= sum1 && sum1 <= sum2)
200dc7c36e4SJohn Marino     new_chunk = call_chunkfun (h, new_size);
20195b7b453SJohn Marino   if (!new_chunk)
20295b7b453SJohn Marino     (*obstack_alloc_failed_handler)();
20395b7b453SJohn Marino   h->chunk = new_chunk;
20495b7b453SJohn Marino   new_chunk->prev = old_chunk;
20595b7b453SJohn Marino   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
20695b7b453SJohn Marino 
20795b7b453SJohn Marino   /* Compute an aligned object_base in the new chunk */
20895b7b453SJohn Marino   object_base =
20995b7b453SJohn Marino     __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
21095b7b453SJohn Marino 
211dc7c36e4SJohn Marino   /* Move the existing object to the new chunk.  */
212dc7c36e4SJohn Marino   memcpy (object_base, h->object_base, obj_size);
21395b7b453SJohn Marino 
21495b7b453SJohn Marino   /* If the object just copied was the only data in OLD_CHUNK,
21595b7b453SJohn Marino      free that chunk and remove it from the chain.
21695b7b453SJohn Marino      But not if that chunk might contain an empty object.  */
21795b7b453SJohn Marino   if (!h->maybe_empty_object
21895b7b453SJohn Marino       && (h->object_base
21995b7b453SJohn Marino           == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
22095b7b453SJohn Marino                           h->alignment_mask)))
22195b7b453SJohn Marino     {
22295b7b453SJohn Marino       new_chunk->prev = old_chunk->prev;
223dc7c36e4SJohn Marino       call_freefun (h, old_chunk);
22495b7b453SJohn Marino     }
22595b7b453SJohn Marino 
22695b7b453SJohn Marino   h->object_base = object_base;
22795b7b453SJohn Marino   h->next_free = h->object_base + obj_size;
22895b7b453SJohn Marino   /* The new chunk certainly contains no empty object yet.  */
22995b7b453SJohn Marino   h->maybe_empty_object = 0;
23095b7b453SJohn Marino }
23195b7b453SJohn Marino 
23295b7b453SJohn Marino /* Return nonzero if object OBJ has been allocated from obstack H.
23395b7b453SJohn Marino    This is here for debugging.
23495b7b453SJohn Marino    If you use it in a program, you are probably losing.  */
23595b7b453SJohn Marino 
23695b7b453SJohn Marino /* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
23795b7b453SJohn Marino    obstack.h because it is just for debugging.  */
238680a9cb8SJohn Marino int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
23995b7b453SJohn Marino 
24095b7b453SJohn Marino int
_obstack_allocated_p(struct obstack * h,void * obj)24195b7b453SJohn Marino _obstack_allocated_p (struct obstack *h, void *obj)
24295b7b453SJohn Marino {
243680a9cb8SJohn Marino   struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
244680a9cb8SJohn Marino   struct _obstack_chunk *plp;   /* point to previous chunk if any */
24595b7b453SJohn Marino 
24695b7b453SJohn Marino   lp = (h)->chunk;
24795b7b453SJohn Marino   /* We use >= rather than > since the object cannot be exactly at
24895b7b453SJohn Marino      the beginning of the chunk but might be an empty object exactly
24995b7b453SJohn Marino      at the end of an adjacent chunk.  */
25095b7b453SJohn Marino   while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
25195b7b453SJohn Marino     {
25295b7b453SJohn Marino       plp = lp->prev;
25395b7b453SJohn Marino       lp = plp;
25495b7b453SJohn Marino     }
25595b7b453SJohn Marino   return lp != 0;
25695b7b453SJohn Marino }
257680a9cb8SJohn Marino 
25895b7b453SJohn Marino /* Free objects in obstack H, including OBJ and everything allocate
25995b7b453SJohn Marino    more recently than OBJ.  If OBJ is zero, free everything in H.  */
26095b7b453SJohn Marino 
26195b7b453SJohn Marino void
_obstack_free(struct obstack * h,void * obj)262dc7c36e4SJohn Marino _obstack_free (struct obstack *h, void *obj)
26395b7b453SJohn Marino {
264680a9cb8SJohn Marino   struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
265680a9cb8SJohn Marino   struct _obstack_chunk *plp;   /* point to previous chunk if any */
26695b7b453SJohn Marino 
26795b7b453SJohn Marino   lp = h->chunk;
26895b7b453SJohn Marino   /* We use >= because there cannot be an object at the beginning of a chunk.
26995b7b453SJohn Marino      But there can be an empty object at that address
27095b7b453SJohn Marino      at the end of another chunk.  */
27195b7b453SJohn Marino   while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
27295b7b453SJohn Marino     {
27395b7b453SJohn Marino       plp = lp->prev;
274dc7c36e4SJohn Marino       call_freefun (h, lp);
27595b7b453SJohn Marino       lp = plp;
27695b7b453SJohn Marino       /* If we switch chunks, we can't tell whether the new current
27795b7b453SJohn Marino          chunk contains an empty object, so assume that it may.  */
27895b7b453SJohn Marino       h->maybe_empty_object = 1;
27995b7b453SJohn Marino     }
28095b7b453SJohn Marino   if (lp)
28195b7b453SJohn Marino     {
28295b7b453SJohn Marino       h->object_base = h->next_free = (char *) (obj);
28395b7b453SJohn Marino       h->chunk_limit = lp->limit;
28495b7b453SJohn Marino       h->chunk = lp;
28595b7b453SJohn Marino     }
28695b7b453SJohn Marino   else if (obj != 0)
28795b7b453SJohn Marino     /* obj is not in any of the chunks! */
28895b7b453SJohn Marino     abort ();
28995b7b453SJohn Marino }
29095b7b453SJohn Marino 
291dc7c36e4SJohn Marino _OBSTACK_SIZE_T
_obstack_memory_used(struct obstack * h)29295b7b453SJohn Marino _obstack_memory_used (struct obstack *h)
29395b7b453SJohn Marino {
294680a9cb8SJohn Marino   struct _obstack_chunk *lp;
295dc7c36e4SJohn Marino   _OBSTACK_SIZE_T nbytes = 0;
29695b7b453SJohn Marino 
29795b7b453SJohn Marino   for (lp = h->chunk; lp != 0; lp = lp->prev)
29895b7b453SJohn Marino     {
29995b7b453SJohn Marino       nbytes += lp->limit - (char *) lp;
30095b7b453SJohn Marino     }
30195b7b453SJohn Marino   return nbytes;
30295b7b453SJohn Marino }
303680a9cb8SJohn Marino 
304dc7c36e4SJohn Marino # ifndef _OBSTACK_NO_ERROR_HANDLER
30595b7b453SJohn Marino /* Define the error handler.  */
306dc7c36e4SJohn Marino #  include <stdio.h>
307dc7c36e4SJohn Marino 
308dc7c36e4SJohn Marino /* Exit value used when 'print_and_abort' is used.  */
309dc7c36e4SJohn Marino #  ifdef _LIBC
310dc7c36e4SJohn Marino int obstack_exit_failure = EXIT_FAILURE;
311dc7c36e4SJohn Marino #  else
312dc7c36e4SJohn Marino #   include "exitfail.h"
313dc7c36e4SJohn Marino #   define obstack_exit_failure exit_failure
314dc7c36e4SJohn Marino #  endif
315dc7c36e4SJohn Marino 
31695b7b453SJohn Marino #  ifdef _LIBC
31795b7b453SJohn Marino #   include <libintl.h>
31895b7b453SJohn Marino #  else
31995b7b453SJohn Marino #   include "gettext.h"
32095b7b453SJohn Marino #  endif
32195b7b453SJohn Marino #  ifndef _
32295b7b453SJohn Marino #   define _(msgid) gettext (msgid)
32395b7b453SJohn Marino #  endif
32495b7b453SJohn Marino 
32595b7b453SJohn Marino #  ifdef _LIBC
32695b7b453SJohn Marino #   include <libio/iolibio.h>
32795b7b453SJohn Marino #  endif
32895b7b453SJohn Marino 
329cf28ed85SJohn Marino static _Noreturn void
print_and_abort(void)33095b7b453SJohn Marino print_and_abort (void)
33195b7b453SJohn Marino {
33295b7b453SJohn Marino   /* Don't change any of these strings.  Yes, it would be possible to add
33395b7b453SJohn Marino      the newline to the string and use fputs or so.  But this must not
33495b7b453SJohn Marino      happen because the "memory exhausted" message appears in other places
33595b7b453SJohn Marino      like this and the translation should be reused instead of creating
33695b7b453SJohn Marino      a very similar string which requires a separate translation.  */
33795b7b453SJohn Marino #  ifdef _LIBC
33895b7b453SJohn Marino   (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
33995b7b453SJohn Marino #  else
34095b7b453SJohn Marino   fprintf (stderr, "%s\n", _("memory exhausted"));
34195b7b453SJohn Marino #  endif
34295b7b453SJohn Marino   exit (obstack_exit_failure);
34395b7b453SJohn Marino }
34495b7b453SJohn Marino 
345dc7c36e4SJohn Marino /* The functions allocating more room by calling 'obstack_chunk_alloc'
346dc7c36e4SJohn Marino    jump to the handler pointed to by 'obstack_alloc_failed_handler'.
347dc7c36e4SJohn Marino    This can be set to a user defined function which should either
348dc7c36e4SJohn Marino    abort gracefully or use longjump - but shouldn't return.  This
349dc7c36e4SJohn Marino    variable by default points to the internal function
350dc7c36e4SJohn Marino    'print_and_abort'.  */
351*09d4459fSDaniel Fojt __attribute_noreturn__ void (*obstack_alloc_failed_handler) (void)
352*09d4459fSDaniel Fojt   = print_and_abort;
353dc7c36e4SJohn Marino # endif /* !_OBSTACK_NO_ERROR_HANDLER */
354dc7c36e4SJohn Marino #endif /* !_OBSTACK_ELIDE_CODE */
355