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