116dce513Schristos /* obstack.c - subroutines used implicitly by object stack macros
2*e992f068Schristos Copyright (C) 1988-2022 Free Software Foundation, Inc.
316dce513Schristos This file is part of the GNU C Library.
416dce513Schristos
516dce513Schristos The GNU C Library is free software; you can redistribute it and/or
616dce513Schristos modify it under the terms of the GNU Lesser General Public
716dce513Schristos License as published by the Free Software Foundation; either
816dce513Schristos version 2.1 of the License, or (at your option) any later version.
916dce513Schristos
1016dce513Schristos The GNU C Library is distributed in the hope that it will be useful,
1116dce513Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
1216dce513Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1316dce513Schristos Lesser General Public License for more details.
1416dce513Schristos
1516dce513Schristos You should have received a copy of the GNU Lesser General Public
1616dce513Schristos License along with the GNU C Library; if not, see
1716dce513Schristos <http://www.gnu.org/licenses/>. */
1816dce513Schristos
1916dce513Schristos
2016dce513Schristos #ifdef _LIBC
2116dce513Schristos # include <obstack.h>
2216dce513Schristos #else
2316dce513Schristos # include <config.h>
2416dce513Schristos # include "obstack.h"
2516dce513Schristos #endif
2616dce513Schristos
2716dce513Schristos /* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
2816dce513Schristos obstack.h must be incremented whenever callers compiled using an old
2916dce513Schristos obstack.h can no longer properly call the functions in this file. */
3016dce513Schristos
3116dce513Schristos /* Comment out all this code if we are using the GNU C Library, and are not
3216dce513Schristos actually compiling the library itself, and the installed library
3316dce513Schristos supports the same library interface we do. This code is part of the GNU
3416dce513Schristos C Library, but also included in many other GNU distributions. Compiling
3516dce513Schristos and linking in this code is a waste when using the GNU C library
3616dce513Schristos (especially if it is a shared library). Rather than having every GNU
3716dce513Schristos program understand 'configure --with-gnu-libc' and omit the object
3816dce513Schristos files, it is simpler to just do this in the source for each such file. */
3916dce513Schristos #if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
4016dce513Schristos # include <gnu-versions.h>
4116dce513Schristos # if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION \
4216dce513Schristos || (_GNU_OBSTACK_INTERFACE_VERSION == 1 \
4316dce513Schristos && _OBSTACK_INTERFACE_VERSION == 2 \
4416dce513Schristos && defined SIZEOF_INT && defined SIZEOF_SIZE_T \
4516dce513Schristos && SIZEOF_INT == SIZEOF_SIZE_T))
4616dce513Schristos # define _OBSTACK_ELIDE_CODE
4716dce513Schristos # endif
4816dce513Schristos #endif
4916dce513Schristos
5016dce513Schristos #ifndef _OBSTACK_ELIDE_CODE
5116dce513Schristos /* If GCC, or if an oddball (testing?) host that #defines __alignof__,
5216dce513Schristos use the already-supplied __alignof__. Otherwise, this must be Gnulib
5316dce513Schristos (as glibc assumes GCC); defer to Gnulib's alignof_type. */
5416dce513Schristos # if !defined __GNUC__ && !defined __IBM__ALIGNOF__ && !defined __alignof__
5516dce513Schristos # if defined __cplusplus
5616dce513Schristos template <class type> struct alignof_helper { char __slot1; type __slot2; };
5716dce513Schristos # define __alignof__(type) offsetof (alignof_helper<type>, __slot2)
5816dce513Schristos # else
5916dce513Schristos # define __alignof__(type) \
6016dce513Schristos offsetof (struct { char __slot1; type __slot2; }, __slot2)
6116dce513Schristos # endif
6216dce513Schristos # endif
6316dce513Schristos # include <stdlib.h>
6416dce513Schristos # include <stdint.h>
6516dce513Schristos
6616dce513Schristos # ifndef MAX
6716dce513Schristos # define MAX(a,b) ((a) > (b) ? (a) : (b))
6816dce513Schristos # endif
6916dce513Schristos
7016dce513Schristos /* Determine default alignment. */
7116dce513Schristos
7216dce513Schristos /* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
7316dce513Schristos But in fact it might be less smart and round addresses to as much as
7416dce513Schristos DEFAULT_ROUNDING. So we prepare for it to do that.
7516dce513Schristos
7616dce513Schristos DEFAULT_ALIGNMENT cannot be an enum constant; see gnulib's alignof.h. */
7716dce513Schristos #define DEFAULT_ALIGNMENT MAX (__alignof__ (long double), \
7816dce513Schristos MAX (__alignof__ (uintmax_t), \
7916dce513Schristos __alignof__ (void *)))
8016dce513Schristos #define DEFAULT_ROUNDING MAX (sizeof (long double), \
8116dce513Schristos MAX (sizeof (uintmax_t), \
8216dce513Schristos sizeof (void *)))
8316dce513Schristos
8416dce513Schristos /* Call functions with either the traditional malloc/free calling
8516dce513Schristos interface, or the mmalloc/mfree interface (that adds an extra first
8616dce513Schristos argument), based on the value of use_extra_arg. */
8716dce513Schristos
8816dce513Schristos static void *
call_chunkfun(struct obstack * h,size_t size)8916dce513Schristos call_chunkfun (struct obstack *h, size_t size)
9016dce513Schristos {
9116dce513Schristos if (h->use_extra_arg)
9216dce513Schristos return h->chunkfun.extra (h->extra_arg, size);
9316dce513Schristos else
9416dce513Schristos return h->chunkfun.plain (size);
9516dce513Schristos }
9616dce513Schristos
9716dce513Schristos static void
call_freefun(struct obstack * h,void * old_chunk)9816dce513Schristos call_freefun (struct obstack *h, void *old_chunk)
9916dce513Schristos {
10016dce513Schristos if (h->use_extra_arg)
10116dce513Schristos h->freefun.extra (h->extra_arg, old_chunk);
10216dce513Schristos else
10316dce513Schristos h->freefun.plain (old_chunk);
10416dce513Schristos }
10516dce513Schristos
10616dce513Schristos
10716dce513Schristos /* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
10816dce513Schristos Objects start on multiples of ALIGNMENT (0 means use default).
10916dce513Schristos
11016dce513Schristos Return nonzero if successful, calls obstack_alloc_failed_handler if
11116dce513Schristos allocation fails. */
11216dce513Schristos
11316dce513Schristos static int
_obstack_begin_worker(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment)11416dce513Schristos _obstack_begin_worker (struct obstack *h,
11516dce513Schristos _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment)
11616dce513Schristos {
11716dce513Schristos struct _obstack_chunk *chunk; /* points to new chunk */
11816dce513Schristos
11916dce513Schristos if (alignment == 0)
12016dce513Schristos alignment = DEFAULT_ALIGNMENT;
12116dce513Schristos if (size == 0)
12216dce513Schristos /* Default size is what GNU malloc can fit in a 4096-byte block. */
12316dce513Schristos {
12416dce513Schristos /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
12516dce513Schristos Use the values for range checking, because if range checking is off,
12616dce513Schristos the extra bytes won't be missed terribly, but if range checking is on
12716dce513Schristos and we used a larger request, a whole extra 4096 bytes would be
12816dce513Schristos allocated.
12916dce513Schristos
13016dce513Schristos These number are irrelevant to the new GNU malloc. I suspect it is
13116dce513Schristos less sensitive to the size of the request. */
13216dce513Schristos int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
13316dce513Schristos + 4 + DEFAULT_ROUNDING - 1)
13416dce513Schristos & ~(DEFAULT_ROUNDING - 1));
13516dce513Schristos size = 4096 - extra;
13616dce513Schristos }
13716dce513Schristos
13816dce513Schristos h->chunk_size = size;
13916dce513Schristos h->alignment_mask = alignment - 1;
14016dce513Schristos
14116dce513Schristos chunk = (struct _obstack_chunk *) call_chunkfun (h, h->chunk_size);
14216dce513Schristos if (!chunk)
14316dce513Schristos (*obstack_alloc_failed_handler) ();
14416dce513Schristos h->chunk = chunk;
14516dce513Schristos h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
14616dce513Schristos alignment - 1);
14716dce513Schristos h->chunk_limit = chunk->limit = (char *) chunk + h->chunk_size;
14816dce513Schristos chunk->prev = 0;
14916dce513Schristos /* The initial chunk now contains no empty object. */
15016dce513Schristos h->maybe_empty_object = 0;
15116dce513Schristos h->alloc_failed = 0;
15216dce513Schristos return 1;
15316dce513Schristos }
15416dce513Schristos
15516dce513Schristos int
_obstack_begin(struct obstack * h,_OBSTACK_SIZE_T size,_OBSTACK_SIZE_T alignment,void * (* chunkfun)(size_t),void (* freefun)(void *))15616dce513Schristos _obstack_begin (struct obstack *h,
15716dce513Schristos _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
15816dce513Schristos void *(*chunkfun) (size_t),
15916dce513Schristos void (*freefun) (void *))
16016dce513Schristos {
16116dce513Schristos h->chunkfun.plain = chunkfun;
16216dce513Schristos h->freefun.plain = freefun;
16316dce513Schristos h->use_extra_arg = 0;
16416dce513Schristos return _obstack_begin_worker (h, size, alignment);
16516dce513Schristos }
16616dce513Schristos
16716dce513Schristos 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)16816dce513Schristos _obstack_begin_1 (struct obstack *h,
16916dce513Schristos _OBSTACK_SIZE_T size, _OBSTACK_SIZE_T alignment,
17016dce513Schristos void *(*chunkfun) (void *, size_t),
17116dce513Schristos void (*freefun) (void *, void *),
17216dce513Schristos void *arg)
17316dce513Schristos {
17416dce513Schristos h->chunkfun.extra = chunkfun;
17516dce513Schristos h->freefun.extra = freefun;
17616dce513Schristos h->extra_arg = arg;
17716dce513Schristos h->use_extra_arg = 1;
17816dce513Schristos return _obstack_begin_worker (h, size, alignment);
17916dce513Schristos }
18016dce513Schristos
18116dce513Schristos /* Allocate a new current chunk for the obstack *H
18216dce513Schristos on the assumption that LENGTH bytes need to be added
18316dce513Schristos to the current object, or a new object of length LENGTH allocated.
18416dce513Schristos Copies any partial object from the end of the old chunk
18516dce513Schristos to the beginning of the new one. */
18616dce513Schristos
18716dce513Schristos void
_obstack_newchunk(struct obstack * h,_OBSTACK_SIZE_T length)18816dce513Schristos _obstack_newchunk (struct obstack *h, _OBSTACK_SIZE_T length)
18916dce513Schristos {
19016dce513Schristos struct _obstack_chunk *old_chunk = h->chunk;
19116dce513Schristos struct _obstack_chunk *new_chunk = 0;
19216dce513Schristos size_t obj_size = h->next_free - h->object_base;
19316dce513Schristos char *object_base;
19416dce513Schristos
19516dce513Schristos /* Compute size for new chunk. */
19616dce513Schristos size_t sum1 = obj_size + length;
19716dce513Schristos size_t sum2 = sum1 + h->alignment_mask;
19816dce513Schristos size_t new_size = sum2 + (obj_size >> 3) + 100;
19916dce513Schristos if (new_size < sum2)
20016dce513Schristos new_size = sum2;
20116dce513Schristos if (new_size < h->chunk_size)
20216dce513Schristos new_size = h->chunk_size;
20316dce513Schristos
20416dce513Schristos /* Allocate and initialize the new chunk. */
20516dce513Schristos if (obj_size <= sum1 && sum1 <= sum2)
20616dce513Schristos new_chunk = (struct _obstack_chunk *) call_chunkfun (h, new_size);
20716dce513Schristos if (!new_chunk)
20816dce513Schristos (*obstack_alloc_failed_handler)();
20916dce513Schristos h->chunk = new_chunk;
21016dce513Schristos new_chunk->prev = old_chunk;
21116dce513Schristos new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
21216dce513Schristos
21316dce513Schristos /* Compute an aligned object_base in the new chunk */
21416dce513Schristos object_base =
21516dce513Schristos __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
21616dce513Schristos
21716dce513Schristos /* Move the existing object to the new chunk. */
21816dce513Schristos memcpy (object_base, h->object_base, obj_size);
21916dce513Schristos
22016dce513Schristos /* If the object just copied was the only data in OLD_CHUNK,
22116dce513Schristos free that chunk and remove it from the chain.
22216dce513Schristos But not if that chunk might contain an empty object. */
22316dce513Schristos if (!h->maybe_empty_object
22416dce513Schristos && (h->object_base
22516dce513Schristos == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
22616dce513Schristos h->alignment_mask)))
22716dce513Schristos {
22816dce513Schristos new_chunk->prev = old_chunk->prev;
22916dce513Schristos call_freefun (h, old_chunk);
23016dce513Schristos }
23116dce513Schristos
23216dce513Schristos h->object_base = object_base;
23316dce513Schristos h->next_free = h->object_base + obj_size;
23416dce513Schristos /* The new chunk certainly contains no empty object yet. */
23516dce513Schristos h->maybe_empty_object = 0;
23616dce513Schristos }
23716dce513Schristos
23816dce513Schristos /* Return nonzero if object OBJ has been allocated from obstack H.
23916dce513Schristos This is here for debugging.
24016dce513Schristos If you use it in a program, you are probably losing. */
24116dce513Schristos
24216dce513Schristos /* Suppress -Wmissing-prototypes warning. We don't want to declare this in
24316dce513Schristos obstack.h because it is just for debugging. */
24416dce513Schristos int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
24516dce513Schristos
24616dce513Schristos int
_obstack_allocated_p(struct obstack * h,void * obj)24716dce513Schristos _obstack_allocated_p (struct obstack *h, void *obj)
24816dce513Schristos {
24916dce513Schristos struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
25016dce513Schristos struct _obstack_chunk *plp; /* point to previous chunk if any */
25116dce513Schristos
25216dce513Schristos lp = (h)->chunk;
25316dce513Schristos /* We use >= rather than > since the object cannot be exactly at
25416dce513Schristos the beginning of the chunk but might be an empty object exactly
25516dce513Schristos at the end of an adjacent chunk. */
25616dce513Schristos while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
25716dce513Schristos {
25816dce513Schristos plp = lp->prev;
25916dce513Schristos lp = plp;
26016dce513Schristos }
26116dce513Schristos return lp != 0;
26216dce513Schristos }
26316dce513Schristos
26416dce513Schristos /* Free objects in obstack H, including OBJ and everything allocate
26516dce513Schristos more recently than OBJ. If OBJ is zero, free everything in H. */
26616dce513Schristos
26716dce513Schristos void
_obstack_free(struct obstack * h,void * obj)26816dce513Schristos _obstack_free (struct obstack *h, void *obj)
26916dce513Schristos {
27016dce513Schristos struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
27116dce513Schristos struct _obstack_chunk *plp; /* point to previous chunk if any */
27216dce513Schristos
27316dce513Schristos lp = h->chunk;
27416dce513Schristos /* We use >= because there cannot be an object at the beginning of a chunk.
27516dce513Schristos But there can be an empty object at that address
27616dce513Schristos at the end of another chunk. */
27716dce513Schristos while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
27816dce513Schristos {
27916dce513Schristos plp = lp->prev;
28016dce513Schristos call_freefun (h, lp);
28116dce513Schristos lp = plp;
28216dce513Schristos /* If we switch chunks, we can't tell whether the new current
28316dce513Schristos chunk contains an empty object, so assume that it may. */
28416dce513Schristos h->maybe_empty_object = 1;
28516dce513Schristos }
28616dce513Schristos if (lp)
28716dce513Schristos {
28816dce513Schristos h->object_base = h->next_free = (char *) (obj);
28916dce513Schristos h->chunk_limit = lp->limit;
29016dce513Schristos h->chunk = lp;
29116dce513Schristos }
29216dce513Schristos else if (obj != 0)
29316dce513Schristos /* obj is not in any of the chunks! */
29416dce513Schristos abort ();
29516dce513Schristos }
29616dce513Schristos
29716dce513Schristos _OBSTACK_SIZE_T
_obstack_memory_used(struct obstack * h)29816dce513Schristos _obstack_memory_used (struct obstack *h)
29916dce513Schristos {
30016dce513Schristos struct _obstack_chunk *lp;
30116dce513Schristos _OBSTACK_SIZE_T nbytes = 0;
30216dce513Schristos
30316dce513Schristos for (lp = h->chunk; lp != 0; lp = lp->prev)
30416dce513Schristos {
30516dce513Schristos nbytes += lp->limit - (char *) lp;
30616dce513Schristos }
30716dce513Schristos return nbytes;
30816dce513Schristos }
30916dce513Schristos
31016dce513Schristos # ifndef _OBSTACK_NO_ERROR_HANDLER
31116dce513Schristos /* Define the error handler. */
31216dce513Schristos # include <stdio.h>
31316dce513Schristos
31416dce513Schristos /* Exit value used when 'print_and_abort' is used. */
31516dce513Schristos # ifdef _LIBC
31616dce513Schristos int obstack_exit_failure = EXIT_FAILURE;
31716dce513Schristos # else
31816dce513Schristos # ifndef EXIT_FAILURE
31916dce513Schristos # define EXIT_FAILURE 1
32016dce513Schristos # endif
32116dce513Schristos # define obstack_exit_failure EXIT_FAILURE
32216dce513Schristos # endif
32316dce513Schristos
32416dce513Schristos # if defined _LIBC || (HAVE_LIBINTL_H && ENABLE_NLS)
32516dce513Schristos # include <libintl.h>
32616dce513Schristos # ifndef _
32716dce513Schristos # define _(msgid) gettext (msgid)
32816dce513Schristos # endif
32916dce513Schristos # else
33016dce513Schristos # ifndef _
33116dce513Schristos # define _(msgid) (msgid)
33216dce513Schristos # endif
33316dce513Schristos # endif
33416dce513Schristos
33516dce513Schristos # if !(defined _Noreturn \
33616dce513Schristos || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112))
33716dce513Schristos # if ((defined __GNUC__ \
33816dce513Schristos && (__GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))) \
33916dce513Schristos || (defined __SUNPRO_C && __SUNPRO_C >= 0x5110))
34016dce513Schristos # define _Noreturn __attribute__ ((__noreturn__))
34116dce513Schristos # elif defined _MSC_VER && _MSC_VER >= 1200
34216dce513Schristos # define _Noreturn __declspec (noreturn)
34316dce513Schristos # else
34416dce513Schristos # define _Noreturn
34516dce513Schristos # endif
34616dce513Schristos # endif
34716dce513Schristos
34816dce513Schristos # ifdef _LIBC
34916dce513Schristos # include <libio/iolibio.h>
35016dce513Schristos # endif
35116dce513Schristos
35216dce513Schristos static _Noreturn void
print_and_abort(void)35316dce513Schristos print_and_abort (void)
35416dce513Schristos {
35516dce513Schristos /* Don't change any of these strings. Yes, it would be possible to add
35616dce513Schristos the newline to the string and use fputs or so. But this must not
35716dce513Schristos happen because the "memory exhausted" message appears in other places
35816dce513Schristos like this and the translation should be reused instead of creating
35916dce513Schristos a very similar string which requires a separate translation. */
36016dce513Schristos # ifdef _LIBC
36116dce513Schristos (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
36216dce513Schristos # else
36316dce513Schristos fprintf (stderr, "%s\n", _("memory exhausted"));
36416dce513Schristos # endif
36516dce513Schristos exit (obstack_exit_failure);
36616dce513Schristos }
36716dce513Schristos
36816dce513Schristos /* The functions allocating more room by calling 'obstack_chunk_alloc'
36916dce513Schristos jump to the handler pointed to by 'obstack_alloc_failed_handler'.
37016dce513Schristos This can be set to a user defined function which should either
37116dce513Schristos abort gracefully or use longjump - but shouldn't return. This
37216dce513Schristos variable by default points to the internal function
37316dce513Schristos 'print_and_abort'. */
37416dce513Schristos void (*obstack_alloc_failed_handler) (void) = print_and_abort;
37516dce513Schristos # endif /* !_OBSTACK_NO_ERROR_HANDLER */
37616dce513Schristos #endif /* !_OBSTACK_ELIDE_CODE */
377