12a6b7db3Sskrll /* obstack.c - subroutines used implicitly by object stack macros
2*f22f0ef4Schristos    Copyright (C) 1988-2022 Free Software Foundation, Inc.
35ba6b03cSchristos    This file is part of the GNU C Library.
42a6b7db3Sskrll 
55ba6b03cSchristos    The GNU C Library is free software; you can redistribute it and/or
65ba6b03cSchristos    modify it under the terms of the GNU Lesser General Public
75ba6b03cSchristos    License as published by the Free Software Foundation; either
85ba6b03cSchristos    version 2.1 of the License, or (at your option) any later version.
92a6b7db3Sskrll 
105ba6b03cSchristos    The GNU C Library is distributed in the hope that it will be useful,
112a6b7db3Sskrll    but WITHOUT ANY WARRANTY; without even the implied warranty of
125ba6b03cSchristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
135ba6b03cSchristos    Lesser General Public License for more details.
142a6b7db3Sskrll 
155ba6b03cSchristos    You should have received a copy of the GNU Lesser General Public
165ba6b03cSchristos    License along with the GNU C Library; if not, see
175ba6b03cSchristos    <http://www.gnu.org/licenses/>.  */
182a6b7db3Sskrll 
195ba6b03cSchristos 
205ba6b03cSchristos #ifdef _LIBC
215ba6b03cSchristos # include <obstack.h>
225ba6b03cSchristos #else
232a6b7db3Sskrll # include <config.h>
245ba6b03cSchristos # include "obstack.h"
252a6b7db3Sskrll #endif
262a6b7db3Sskrll 
275ba6b03cSchristos /* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
285ba6b03cSchristos    obstack.h must be incremented whenever callers compiled using an old
295ba6b03cSchristos    obstack.h can no longer properly call the functions in this file.  */
302a6b7db3Sskrll 
312a6b7db3Sskrll /* Comment out all this code if we are using the GNU C Library, and are not
322a6b7db3Sskrll    actually compiling the library itself, and the installed library
332a6b7db3Sskrll    supports the same library interface we do.  This code is part of the GNU
342a6b7db3Sskrll    C Library, but also included in many other GNU distributions.  Compiling
352a6b7db3Sskrll    and linking in this code is a waste when using the GNU C library
362a6b7db3Sskrll    (especially if it is a shared library).  Rather than having every GNU
375ba6b03cSchristos    program understand 'configure --with-gnu-libc' and omit the object
382a6b7db3Sskrll    files, it is simpler to just do this in the source for each such file.  */
395ba6b03cSchristos #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
402a6b7db3Sskrll # include <gnu-versions.h>
415ba6b03cSchristos # if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION	      \
425ba6b03cSchristos       || (_GNU_OBSTACK_INTERFACE_VERSION == 1				      \
435ba6b03cSchristos           && _OBSTACK_INTERFACE_VERSION == 2				      \
445ba6b03cSchristos           && defined SIZEOF_INT && defined SIZEOF_SIZE_T		      \
455ba6b03cSchristos           && SIZEOF_INT == SIZEOF_SIZE_T))
465ba6b03cSchristos #  define _OBSTACK_ELIDE_CODE
472a6b7db3Sskrll # endif
482a6b7db3Sskrll #endif
492a6b7db3Sskrll 
505ba6b03cSchristos #ifndef _OBSTACK_ELIDE_CODE
515ba6b03cSchristos /* If GCC, or if an oddball (testing?) host that #defines __alignof__,
525ba6b03cSchristos    use the already-supplied __alignof__.  Otherwise, this must be Gnulib
535ba6b03cSchristos    (as glibc assumes GCC); defer to Gnulib's alignof_type.  */
545ba6b03cSchristos # if !defined __GNUC__ && !defined __IBM__ALIGNOF__ && !defined __alignof__
555ba6b03cSchristos #  if defined __cplusplus
565ba6b03cSchristos template <class type> struct alignof_helper { char __slot1; type __slot2; };
575ba6b03cSchristos #   define __alignof__(type) offsetof (alignof_helper<type>, __slot2)
585ba6b03cSchristos #  else
595ba6b03cSchristos #   define __alignof__(type)						      \
605ba6b03cSchristos   offsetof (struct { char __slot1; type __slot2; }, __slot2)
615ba6b03cSchristos #  endif
625ba6b03cSchristos # endif
635ba6b03cSchristos # include <stdlib.h>
645ba6b03cSchristos # include <stdint.h>
652a6b7db3Sskrll 
665ba6b03cSchristos # ifndef MAX
675ba6b03cSchristos #  define MAX(a,b) ((a) > (b) ? (a) : (b))
685ba6b03cSchristos # endif
692a6b7db3Sskrll 
702a6b7db3Sskrll /* Determine default alignment.  */
715ba6b03cSchristos 
722a6b7db3Sskrll /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
732a6b7db3Sskrll    But in fact it might be less smart and round addresses to as much as
745ba6b03cSchristos    DEFAULT_ROUNDING.  So we prepare for it to do that.
752a6b7db3Sskrll 
765ba6b03cSchristos    DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h.  */
775ba6b03cSchristos #define DEFAULT_ALIGNMENT MAX (__alignof__ (long double),		      \
785ba6b03cSchristos                                MAX (__alignof__ (uintmax_t),		      \
795ba6b03cSchristos                                     __alignof__ (void *)))
805ba6b03cSchristos #define DEFAULT_ROUNDING MAX (sizeof (long double),			      \
815ba6b03cSchristos                                MAX (sizeof (uintmax_t),			      \
825ba6b03cSchristos                                     sizeof (void *)))
835ba6b03cSchristos 
845ba6b03cSchristos /* Call functions with either the traditional malloc/free calling
855ba6b03cSchristos    interface, or the mmalloc/mfree interface (that adds an extra first
865ba6b03cSchristos    argument), based on the value of use_extra_arg.  */
875ba6b03cSchristos 
885ba6b03cSchristos static void *
call_chunkfun(struct obstack * h,size_t size)895ba6b03cSchristos call_chunkfun (struct obstack *h, size_t size)
905ba6b03cSchristos {
915ba6b03cSchristos   if (h->use_extra_arg)
925ba6b03cSchristos     return h->chunkfun.extra (h->extra_arg, size);
935ba6b03cSchristos   else
945ba6b03cSchristos     return h->chunkfun.plain (size);
955ba6b03cSchristos }
965ba6b03cSchristos 
975ba6b03cSchristos static void
call_freefun(struct obstack * h,void * old_chunk)985ba6b03cSchristos call_freefun (struct obstack *h, void *old_chunk)
995ba6b03cSchristos {
1005ba6b03cSchristos   if (h->use_extra_arg)
1015ba6b03cSchristos     h->freefun.extra (h->extra_arg, old_chunk);
1025ba6b03cSchristos   else
1035ba6b03cSchristos     h->freefun.plain (old_chunk);
1045ba6b03cSchristos }
1052a6b7db3Sskrll 
1062a6b7db3Sskrll 
1072a6b7db3Sskrll /* Initialize an obstack H for use.  Specify chunk size SIZE (0 means default).
1082a6b7db3Sskrll    Objects start on multiples of ALIGNMENT (0 means use default).
1092a6b7db3Sskrll 
1105ba6b03cSchristos    Return nonzero if successful, calls obstack_alloc_failed_handler if
1115ba6b03cSchristos    allocation fails.  */
1122a6b7db3Sskrll 
1135ba6b03cSchristos static int
_obstack_begin_worker(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment)1145ba6b03cSchristos _obstack_begin_worker (struct obstack *h,
1155ba6b03cSchristos                        _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment)
1162a6b7db3Sskrll {
1175ba6b03cSchristos   struct _obstack_chunk *chunk; /* points to new chunk */
1182a6b7db3Sskrll 
1192a6b7db3Sskrll   if (alignment == 0)
1205ba6b03cSchristos     alignment = DEFAULT_ALIGNMENT;
1212a6b7db3Sskrll   if (size == 0)
1222a6b7db3Sskrll     /* Default size is what GNU malloc can fit in a 4096-byte block.  */
1232a6b7db3Sskrll     {
1242a6b7db3Sskrll       /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
1252a6b7db3Sskrll          Use the values for range checking, because if range checking is off,
1262a6b7db3Sskrll          the extra bytes won't be missed terribly, but if range checking is on
1272a6b7db3Sskrll          and we used a larger request, a whole extra 4096 bytes would be
1282a6b7db3Sskrll          allocated.
1292a6b7db3Sskrll 
1302a6b7db3Sskrll          These number are irrelevant to the new GNU malloc.  I suspect it is
1312a6b7db3Sskrll          less sensitive to the size of the request.  */
1322a6b7db3Sskrll       int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
1332a6b7db3Sskrll                     + 4 + DEFAULT_ROUNDING - 1)
1342a6b7db3Sskrll                    & ~(DEFAULT_ROUNDING - 1));
1352a6b7db3Sskrll       size = 4096 - extra;
1362a6b7db3Sskrll     }
1372a6b7db3Sskrll 
1382a6b7db3Sskrll   h->chunk_size = size;
1392a6b7db3Sskrll   h->alignment_mask = alignment - 1;
1402a6b7db3Sskrll 
1415ba6b03cSchristos   chunk = (struct _obstack_chunk *) call_chunkfun (h, h->chunk_size);
1422a6b7db3Sskrll   if (!chunk)
1432a6b7db3Sskrll     (*obstack_alloc_failed_handler) ();
1445ba6b03cSchristos   h->chunk = chunk;
1455ba6b03cSchristos   h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
1465ba6b03cSchristos                                                alignment - 1);
1475ba6b03cSchristos   h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
1482a6b7db3Sskrll   chunk->prev = 0;
1492a6b7db3Sskrll   /* The initial chunk now contains no empty object.  */
1502a6b7db3Sskrll   h->maybe_empty_object = 0;
1512a6b7db3Sskrll   h->alloc_failed = 0;
1522a6b7db3Sskrll   return 1;
1532a6b7db3Sskrll }
1542a6b7db3Sskrll 
1552a6b7db3Sskrll int
_obstack_begin(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment,void * (* chunkfun)(size_t),void (* freefun)(void *))1565ba6b03cSchristos _obstack_begin (struct obstack *h,
1575ba6b03cSchristos                 _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
1585ba6b03cSchristos                 void *(*chunkfun) (size_t),
1595ba6b03cSchristos                 void (*freefun) (void *))
1602a6b7db3Sskrll {
1615ba6b03cSchristos   h->chunkfun.plain = chunkfun;
1625ba6b03cSchristos   h->freefun.plain = freefun;
1635ba6b03cSchristos   h->use_extra_arg = 0;
1645ba6b03cSchristos   return _obstack_begin_worker (h, size, alignment);
1652a6b7db3Sskrll }
1662a6b7db3Sskrll 
1675ba6b03cSchristos 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)1685ba6b03cSchristos _obstack_begin_1 (struct obstack *h,
1695ba6b03cSchristos                   _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
1705ba6b03cSchristos                   void *(*chunkfun) (void *, size_t),
1715ba6b03cSchristos                   void (*freefun) (void *, void *),
1725ba6b03cSchristos                   void *arg)
1735ba6b03cSchristos {
1745ba6b03cSchristos   h->chunkfun.extra = chunkfun;
1755ba6b03cSchristos   h->freefun.extra = freefun;
1762a6b7db3Sskrll   h->extra_arg = arg;
1772a6b7db3Sskrll   h->use_extra_arg = 1;
1785ba6b03cSchristos   return _obstack_begin_worker (h, size, alignment);
1792a6b7db3Sskrll }
1802a6b7db3Sskrll 
1812a6b7db3Sskrll /* Allocate a new current chunk for the obstack *H
1822a6b7db3Sskrll    on the assumption that LENGTH bytes need to be added
1832a6b7db3Sskrll    to the current object, or a new object of length LENGTH allocated.
1842a6b7db3Sskrll    Copies any partial object from the end of the old chunk
1852a6b7db3Sskrll    to the beginning of the new one.  */
1862a6b7db3Sskrll 
1872a6b7db3Sskrll void
_obstack_newchunk(struct obstack * h,_OBSTACK_SIZE_T length)1885ba6b03cSchristos _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
1892a6b7db3Sskrll {
1905ba6b03cSchristos   struct _obstack_chunk *old_chunk = h->chunk;
1915ba6b03cSchristos   struct _obstack_chunk *new_chunk = 0;
1925ba6b03cSchristos   size_t obj_size = h->next_free - h->object_base;
1935ba6b03cSchristos   char *object_base;
1942a6b7db3Sskrll 
1952a6b7db3Sskrll   /* Compute size for new chunk.  */
1965ba6b03cSchristos   size_t sum1 = obj_size + length;
1975ba6b03cSchristos   size_t sum2 = sum1 + h->alignment_mask;
1985ba6b03cSchristos   size_t new_size = sum2 + (obj_size >> 3) + 100;
1995ba6b03cSchristos   if (new_size < sum2)
2005ba6b03cSchristos     new_size = sum2;
2012a6b7db3Sskrll   if (new_size < h->chunk_size)
2022a6b7db3Sskrll     new_size = h->chunk_size;
2032a6b7db3Sskrll 
2042a6b7db3Sskrll   /* Allocate and initialize the new chunk.  */
2055ba6b03cSchristos   if (obj_size <= sum1 && sum1 <= sum2)
2065ba6b03cSchristos     new_chunk = (struct _obstack_chunk *) call_chunkfun (h, new_size);
2072a6b7db3Sskrll   if (!new_chunk)
2082a6b7db3Sskrll     (*obstack_alloc_failed_handler)();
2092a6b7db3Sskrll   h->chunk = new_chunk;
2102a6b7db3Sskrll   new_chunk->prev = old_chunk;
2112a6b7db3Sskrll   new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
2122a6b7db3Sskrll 
2135ba6b03cSchristos   /* Compute an aligned object_base in the new chunk */
2145ba6b03cSchristos   object_base =
2155ba6b03cSchristos     __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
2165ba6b03cSchristos 
2175ba6b03cSchristos   /* Move the existing object to the new chunk.  */
2185ba6b03cSchristos   memcpy (object_base, h->object_base, obj_size);
2192a6b7db3Sskrll 
2202a6b7db3Sskrll   /* If the object just copied was the only data in OLD_CHUNK,
2212a6b7db3Sskrll      free that chunk and remove it from the chain.
2222a6b7db3Sskrll      But not if that chunk might contain an empty object.  */
2235ba6b03cSchristos   if (!h->maybe_empty_object
2245ba6b03cSchristos       && (h->object_base
2255ba6b03cSchristos           == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
2265ba6b03cSchristos                           h->alignment_mask)))
2272a6b7db3Sskrll     {
2282a6b7db3Sskrll       new_chunk->prev = old_chunk->prev;
2295ba6b03cSchristos       call_freefun (h, old_chunk);
2302a6b7db3Sskrll     }
2312a6b7db3Sskrll 
2325ba6b03cSchristos   h->object_base = object_base;
2332a6b7db3Sskrll   h->next_free = h->object_base + obj_size;
2342a6b7db3Sskrll   /* The new chunk certainly contains no empty object yet.  */
2352a6b7db3Sskrll   h->maybe_empty_object = 0;
2362a6b7db3Sskrll }
2372a6b7db3Sskrll 
2382a6b7db3Sskrll /* Return nonzero if object OBJ has been allocated from obstack H.
2392a6b7db3Sskrll    This is here for debugging.
2402a6b7db3Sskrll    If you use it in a program, you are probably losing.  */
2412a6b7db3Sskrll 
2422a6b7db3Sskrll /* Suppress -Wmissing-prototypes warning.  We don't want to declare this in
2432a6b7db3Sskrll    obstack.h because it is just for debugging.  */
2445ba6b03cSchristos int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
2452a6b7db3Sskrll 
2462a6b7db3Sskrll int
_obstack_allocated_p(struct obstack * h,void * obj)2475ba6b03cSchristos _obstack_allocated_p (struct obstack *h, void *obj)
2482a6b7db3Sskrll {
2495ba6b03cSchristos   struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
2505ba6b03cSchristos   struct _obstack_chunk *plp;   /* point to previous chunk if any */
2512a6b7db3Sskrll 
2522a6b7db3Sskrll   lp = (h)->chunk;
2532a6b7db3Sskrll   /* We use >= rather than > since the object cannot be exactly at
2542a6b7db3Sskrll      the beginning of the chunk but might be an empty object exactly
2552a6b7db3Sskrll      at the end of an adjacent chunk.  */
2565ba6b03cSchristos   while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
2572a6b7db3Sskrll     {
2582a6b7db3Sskrll       plp = lp->prev;
2592a6b7db3Sskrll       lp = plp;
2602a6b7db3Sskrll     }
2612a6b7db3Sskrll   return lp != 0;
2622a6b7db3Sskrll }
2635ba6b03cSchristos 
2642a6b7db3Sskrll /* Free objects in obstack H, including OBJ and everything allocate
2652a6b7db3Sskrll    more recently than OBJ.  If OBJ is zero, free everything in H.  */
2662a6b7db3Sskrll 
2672a6b7db3Sskrll void
_obstack_free(struct obstack * h,void * obj)2685ba6b03cSchristos _obstack_free (struct obstack *h, void *obj)
2692a6b7db3Sskrll {
2705ba6b03cSchristos   struct _obstack_chunk *lp;    /* below addr of any objects in this chunk */
2715ba6b03cSchristos   struct _obstack_chunk *plp;   /* point to previous chunk if any */
2722a6b7db3Sskrll 
2732a6b7db3Sskrll   lp = h->chunk;
2742a6b7db3Sskrll   /* We use >= because there cannot be an object at the beginning of a chunk.
2752a6b7db3Sskrll      But there can be an empty object at that address
2762a6b7db3Sskrll      at the end of another chunk.  */
2775ba6b03cSchristos   while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
2782a6b7db3Sskrll     {
2792a6b7db3Sskrll       plp = lp->prev;
2805ba6b03cSchristos       call_freefun (h, lp);
2812a6b7db3Sskrll       lp = plp;
2822a6b7db3Sskrll       /* If we switch chunks, we can't tell whether the new current
2832a6b7db3Sskrll          chunk contains an empty object, so assume that it may.  */
2842a6b7db3Sskrll       h->maybe_empty_object = 1;
2852a6b7db3Sskrll     }
2862a6b7db3Sskrll   if (lp)
2872a6b7db3Sskrll     {
2882a6b7db3Sskrll       h->object_base = h->next_free = (char *) (obj);
2892a6b7db3Sskrll       h->chunk_limit = lp->limit;
2902a6b7db3Sskrll       h->chunk = lp;
2912a6b7db3Sskrll     }
2922a6b7db3Sskrll   else if (obj != 0)
2932a6b7db3Sskrll     /* obj is not in any of the chunks! */
2942a6b7db3Sskrll     abort ();
2952a6b7db3Sskrll }
2962a6b7db3Sskrll 
2975ba6b03cSchristos _OBSTACK_SIZE_T
_obstack_memory_used(struct obstack * h)2982a6b7db3Sskrll _obstack_memory_used (struct obstack *h)
2992a6b7db3Sskrll {
3005ba6b03cSchristos   struct _obstack_chunk *lp;
3015ba6b03cSchristos   _OBSTACK_SIZE_T nbytes = 0;
3022a6b7db3Sskrll 
3032a6b7db3Sskrll   for (lp = h->chunk; lp != 0; lp = lp->prev)
3042a6b7db3Sskrll     {
3052a6b7db3Sskrll       nbytes += lp->limit - (char *) lp;
3062a6b7db3Sskrll     }
3072a6b7db3Sskrll   return nbytes;
3082a6b7db3Sskrll }
3095ba6b03cSchristos 
3105ba6b03cSchristos # ifndef _OBSTACK_NO_ERROR_HANDLER
3112a6b7db3Sskrll /* Define the error handler.  */
3125ba6b03cSchristos #  include <stdio.h>
3135ba6b03cSchristos 
3145ba6b03cSchristos /* Exit value used when 'print_and_abort' is used.  */
3155ba6b03cSchristos #  ifdef _LIBC
3165ba6b03cSchristos int obstack_exit_failure = EXIT_FAILURE;
3175ba6b03cSchristos #  else
3185ba6b03cSchristos #   ifndef EXIT_FAILURE
3195ba6b03cSchristos #    define EXIT_FAILURE 1
3205ba6b03cSchristos #   endif
3215ba6b03cSchristos #   define obstack_exit_failure EXIT_FAILURE
3225ba6b03cSchristos #  endif
3235ba6b03cSchristos 
3245ba6b03cSchristos #  if defined _LIBC || (HAVE_LIBINTL_H && ENABLE_NLS)
3252a6b7db3Sskrll #   include <libintl.h>
3262a6b7db3Sskrll #   ifndef _
3275ba6b03cSchristos #    define _(msgid) gettext (msgid)
3282a6b7db3Sskrll #   endif
3292a6b7db3Sskrll #  else
3305ba6b03cSchristos #   ifndef _
3315ba6b03cSchristos #    define _(msgid) (msgid)
3322a6b7db3Sskrll #   endif
3332a6b7db3Sskrll #  endif
3342a6b7db3Sskrll 
3355ba6b03cSchristos #  if !(defined _Noreturn						      \
3365ba6b03cSchristos         || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112))
3375ba6b03cSchristos #   if ((defined __GNUC__						      \
3385ba6b03cSchristos 	 && (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)))	      \
3395ba6b03cSchristos 	|| (defined __SUNPRO_C && __SUNPRO_C >= 0x5110))
3405ba6b03cSchristos #    define _Noreturn __attribute__ ((__noreturn__))
3415ba6b03cSchristos #   elif defined _MSC_VER && _MSC_VER >= 1200
3425ba6b03cSchristos #    define _Noreturn __declspec (noreturn)
3435ba6b03cSchristos #   else
3445ba6b03cSchristos #    define _Noreturn
3455ba6b03cSchristos #   endif
3465ba6b03cSchristos #  endif
3475ba6b03cSchristos 
3485ba6b03cSchristos #  ifdef _LIBC
3495ba6b03cSchristos #   include <libio/iolibio.h>
3505ba6b03cSchristos #  endif
3515ba6b03cSchristos 
3525ba6b03cSchristos static _Noreturn void
print_and_abort(void)3532a6b7db3Sskrll print_and_abort (void)
3542a6b7db3Sskrll {
3555ba6b03cSchristos   /* Don't change any of these strings.  Yes, it would be possible to add
3565ba6b03cSchristos      the newline to the string and use fputs or so.  But this must not
3575ba6b03cSchristos      happen because the "memory exhausted" message appears in other places
3585ba6b03cSchristos      like this and the translation should be reused instead of creating
3595ba6b03cSchristos      a very similar string which requires a separate translation.  */
3605ba6b03cSchristos #  ifdef _LIBC
3615ba6b03cSchristos   (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
3625ba6b03cSchristos #  else
3635ba6b03cSchristos   fprintf (stderr, "%s\n", _("memory exhausted"));
3645ba6b03cSchristos #  endif
3652a6b7db3Sskrll   exit (obstack_exit_failure);
3662a6b7db3Sskrll }
3672a6b7db3Sskrll 
3685ba6b03cSchristos /* The functions allocating more room by calling 'obstack_chunk_alloc'
3695ba6b03cSchristos    jump to the handler pointed to by 'obstack_alloc_failed_handler'.
3705ba6b03cSchristos    This can be set to a user defined function which should either
3715ba6b03cSchristos    abort gracefully or use longjump - but shouldn't return.  This
3725ba6b03cSchristos    variable by default points to the internal function
3735ba6b03cSchristos    'print_and_abort'.  */
3745ba6b03cSchristos void (*obstack_alloc_failed_handler) (void) = print_and_abort;
3755ba6b03cSchristos # endif /* !_OBSTACK_NO_ERROR_HANDLER */
3765ba6b03cSchristos #endif /* !_OBSTACK_ELIDE_CODE */
377