]> git.ipfire.org Git - thirdparty/glibc.git/blame - malloc/obstack.c
contrib.texi: update
[thirdparty/glibc.git] / malloc / obstack.c
CommitLineData
f65fd747 1/* obstack.c - subroutines used implicitly by object stack macros
dff8da6b 2 Copyright (C) 1988-2024 Free Software Foundation, Inc.
2fd4de4b 3 This file is part of the GNU C Library.
f65fd747
UD
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
f65fd747
UD
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
f65fd747 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
2fd4de4b 18
f65fd747 19
a20d8dbe 20#ifdef _LIBC
9d1e2b7d 21# include <obstack.h>
2c55cb99 22# include <shlib-compat.h>
a20d8dbe 23#else
b100f9aa 24# include <config.h>
9d1e2b7d 25# include "obstack.h"
a20d8dbe 26#endif
f65fd747
UD
27
28/* NOTE BEFORE MODIFYING THIS FILE: This version number must be
29 incremented whenever callers compiled using an old obstack.h can no
30 longer properly call the functions in this obstack.c. */
f8b87ef0 31#define OBSTACK_INTERFACE_VERSION 1
f65fd747
UD
32
33/* Comment out all this code if we are using the GNU C Library, and are not
34 actually compiling the library itself, and the installed library
35 supports the same library interface we do. This code is part of the GNU
36 C Library, but also included in many other GNU distributions. Compiling
37 and linking in this code is a waste when using the GNU C library
38 (especially if it is a shared library). Rather than having every GNU
b100f9aa 39 program understand 'configure --with-gnu-libc' and omit the object
f65fd747
UD
40 files, it is simpler to just do this in the source for each such file. */
41
6c8dbf00 42#include <stdio.h> /* Random thing to get __GNU_LIBRARY__. */
647eb037
UD
43#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
44# include <gnu-versions.h>
45# if _GNU_OBSTACK_INTERFACE_VERSION == OBSTACK_INTERFACE_VERSION
46# define ELIDE_CODE
47# endif
f65fd747
UD
48#endif
49
2fd4de4b 50#include <stddef.h>
f65fd747
UD
51
52#ifndef ELIDE_CODE
53
54
b100f9aa 55# include <stdint.h>
2fd4de4b 56
f65fd747 57/* Determine default alignment. */
2fd4de4b
RM
58union fooround
59{
60 uintmax_t i;
61 long double d;
62 void *p;
63};
64struct fooalign
65{
66 char c;
67 union fooround u;
68};
f65fd747
UD
69/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT.
70 But in fact it might be less smart and round addresses to as much as
71 DEFAULT_ROUNDING. So we prepare for it to do that. */
2fd4de4b 72enum
6c8dbf00
OB
73{
74 DEFAULT_ALIGNMENT = offsetof (struct fooalign, u),
75 DEFAULT_ROUNDING = sizeof (union fooround)
76};
f65fd747
UD
77
78/* When we copy a long block of data, this is the unit to do it with.
79 On some machines, copying successive ints does not work;
b100f9aa
WN
80 in such a case, redefine COPYING_UNIT to 'long' (if that works)
81 or 'char' as a last resort. */
647eb037
UD
82# ifndef COPYING_UNIT
83# define COPYING_UNIT int
84# endif
f65fd747
UD
85
86
b100f9aa
WN
87/* The functions allocating more room by calling 'obstack_chunk_alloc'
88 jump to the handler pointed to by 'obstack_alloc_failed_handler'.
8325d82c
UD
89 This can be set to a user defined function which should either
90 abort gracefully or use longjump - but shouldn't return. This
91 variable by default points to the internal function
b100f9aa
WN
92 'print_and_abort'. */
93static _Noreturn void print_and_abort (void);
f65fd747 94void (*obstack_alloc_failed_handler) (void) = print_and_abort;
f65fd747 95
b100f9aa 96/* Exit value used when 'print_and_abort' is used. */
9d1e2b7d
UD
97# include <stdlib.h>
98# ifdef _LIBC
f65fd747 99int obstack_exit_failure = EXIT_FAILURE;
9d1e2b7d
UD
100# else
101# include "exitfail.h"
102# define obstack_exit_failure exit_failure
103# endif
f65fd747 104
558c2954 105# ifdef _LIBC
2c55cb99 106# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4)
558c2954
UD
107/* A looong time ago (before 1994, anyway; we're not sure) this global variable
108 was used by non-GNU-C macros to avoid multiple evaluation. The GNU C
109 library still exports it because somebody might use it. */
39b1f617 110struct obstack *_obstack_compat = 0;
2c55cb99
UD
111compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0);
112# endif
558c2954 113# endif
f65fd747
UD
114
115/* Define a macro that either calls functions with the traditional malloc/free
116 calling interface, or calls functions with the mmalloc/mfree interface
117 (that adds an extra first argument), based on the state of use_extra_arg.
118 For free, do not use ?:, since some compilers, like the MIPS compilers,
119 do not allow (expr) ? void : void. */
120
9d1e2b7d 121# define CALL_CHUNKFUN(h, size) \
6c8dbf00
OB
122 (((h)->use_extra_arg) \
123 ? (*(h)->chunkfun)((h)->extra_arg, (size)) \
124 : (*(struct _obstack_chunk *(*)(long))(h)->chunkfun)((size)))
01c901a5 125
9d1e2b7d 126# define CALL_FREEFUN(h, old_chunk) \
01c901a5 127 do { \
6c8dbf00 128 if ((h)->use_extra_arg) \
b100f9aa 129 (*(h)->freefun)((h)->extra_arg, (old_chunk)); \
6c8dbf00 130 else \
b100f9aa 131 (*(void (*)(void *))(h)->freefun)((old_chunk)); \
6c8dbf00
OB
132 } while (0)
133
f65fd747 134
f65fd747
UD
135/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default).
136 Objects start on multiples of ALIGNMENT (0 means use default).
137 CHUNKFUN is the function to use to allocate chunks,
138 and FREEFUN the function to free them.
139
8325d82c
UD
140 Return nonzero if successful, calls obstack_alloc_failed_handler if
141 allocation fails. */
f65fd747
UD
142
143int
9d1e2b7d 144_obstack_begin (struct obstack *h,
b100f9aa
WN
145 int size, int alignment,
146 void *(*chunkfun) (long),
147 void (*freefun) (void *))
f65fd747 148{
2e09a79a 149 struct _obstack_chunk *chunk; /* points to new chunk */
f65fd747
UD
150
151 if (alignment == 0)
2fd4de4b 152 alignment = DEFAULT_ALIGNMENT;
f65fd747 153 if (size == 0)
b100f9aa 154 /* Default size is what GNU malloc can fit in a 4096-byte block. */
f65fd747
UD
155 {
156 /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
b100f9aa
WN
157 Use the values for range checking, because if range checking is off,
158 the extra bytes won't be missed terribly, but if range checking is on
159 and we used a larger request, a whole extra 4096 bytes would be
160 allocated.
f65fd747 161
b100f9aa
WN
162 These number are irrelevant to the new GNU malloc. I suspect it is
163 less sensitive to the size of the request. */
f65fd747 164 int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
b100f9aa
WN
165 + 4 + DEFAULT_ROUNDING - 1)
166 & ~(DEFAULT_ROUNDING - 1));
f65fd747
UD
167 size = 4096 - extra;
168 }
169
b100f9aa
WN
170 h->chunkfun = (struct _obstack_chunk * (*) (void *, long)) chunkfun;
171 h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
f65fd747
UD
172 h->chunk_size = size;
173 h->alignment_mask = alignment - 1;
174 h->use_extra_arg = 0;
175
6c8dbf00 176 chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
f65fd747 177 if (!chunk)
b100f9aa 178 (*obstack_alloc_failed_handler) ();
2fd4de4b 179 h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
b100f9aa 180 alignment - 1);
f65fd747 181 h->chunk_limit = chunk->limit
b100f9aa 182 = (char *) chunk + h->chunk_size;
f65fd747
UD
183 chunk->prev = 0;
184 /* The initial chunk now contains no empty object. */
185 h->maybe_empty_object = 0;
f8b87ef0 186 h->alloc_failed = 0;
f65fd747
UD
187 return 1;
188}
189
190int
9d1e2b7d 191_obstack_begin_1 (struct obstack *h, int size, int alignment,
b100f9aa
WN
192 void *(*chunkfun) (void *, long),
193 void (*freefun) (void *, void *),
194 void *arg)
f65fd747 195{
2e09a79a 196 struct _obstack_chunk *chunk; /* points to new chunk */
f65fd747
UD
197
198 if (alignment == 0)
2fd4de4b 199 alignment = DEFAULT_ALIGNMENT;
f65fd747 200 if (size == 0)
b100f9aa 201 /* Default size is what GNU malloc can fit in a 4096-byte block. */
f65fd747
UD
202 {
203 /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc.
b100f9aa
WN
204 Use the values for range checking, because if range checking is off,
205 the extra bytes won't be missed terribly, but if range checking is on
206 and we used a larger request, a whole extra 4096 bytes would be
207 allocated.
f65fd747 208
b100f9aa
WN
209 These number are irrelevant to the new GNU malloc. I suspect it is
210 less sensitive to the size of the request. */
f65fd747 211 int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1))
b100f9aa
WN
212 + 4 + DEFAULT_ROUNDING - 1)
213 & ~(DEFAULT_ROUNDING - 1));
f65fd747
UD
214 size = 4096 - extra;
215 }
216
b100f9aa
WN
217 h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun;
218 h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun;
f65fd747
UD
219 h->chunk_size = size;
220 h->alignment_mask = alignment - 1;
221 h->extra_arg = arg;
222 h->use_extra_arg = 1;
223
6c8dbf00 224 chunk = h->chunk = CALL_CHUNKFUN (h, h->chunk_size);
f65fd747 225 if (!chunk)
b100f9aa 226 (*obstack_alloc_failed_handler) ();
2fd4de4b 227 h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents,
b100f9aa 228 alignment - 1);
f65fd747 229 h->chunk_limit = chunk->limit
b100f9aa 230 = (char *) chunk + h->chunk_size;
f65fd747
UD
231 chunk->prev = 0;
232 /* The initial chunk now contains no empty object. */
233 h->maybe_empty_object = 0;
f8b87ef0 234 h->alloc_failed = 0;
f65fd747
UD
235 return 1;
236}
237
238/* Allocate a new current chunk for the obstack *H
239 on the assumption that LENGTH bytes need to be added
240 to the current object, or a new object of length LENGTH allocated.
241 Copies any partial object from the end of the old chunk
242 to the beginning of the new one. */
243
244void
9d1e2b7d 245_obstack_newchunk (struct obstack *h, int length)
f65fd747 246{
2e09a79a
JM
247 struct _obstack_chunk *old_chunk = h->chunk;
248 struct _obstack_chunk *new_chunk;
6c8dbf00 249 long new_size;
2e09a79a
JM
250 long obj_size = h->next_free - h->object_base;
251 long i;
39e16978 252 long already;
84832e05 253 char *object_base;
f65fd747
UD
254
255 /* Compute size for new chunk. */
84832e05 256 new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100;
f65fd747
UD
257 if (new_size < h->chunk_size)
258 new_size = h->chunk_size;
259
260 /* Allocate and initialize the new chunk. */
261 new_chunk = CALL_CHUNKFUN (h, new_size);
262 if (!new_chunk)
6c8dbf00 263 (*obstack_alloc_failed_handler)();
f65fd747
UD
264 h->chunk = new_chunk;
265 new_chunk->prev = old_chunk;
266 new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size;
267
84832e05
UD
268 /* Compute an aligned object_base in the new chunk */
269 object_base =
2fd4de4b 270 __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask);
84832e05 271
f65fd747
UD
272 /* Move the existing object to the new chunk.
273 Word at a time is fast and is safe if the object
274 is sufficiently aligned. */
275 if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT)
276 {
277 for (i = obj_size / sizeof (COPYING_UNIT) - 1;
b100f9aa
WN
278 i >= 0; i--)
279 ((COPYING_UNIT *) object_base)[i]
280 = ((COPYING_UNIT *) h->object_base)[i];
f65fd747 281 /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT,
b100f9aa
WN
282 but that can cross a page boundary on a machine
283 which does not do strict alignment for COPYING_UNITS. */
f65fd747
UD
284 already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT);
285 }
286 else
287 already = 0;
288 /* Copy remaining bytes one by one. */
289 for (i = already; i < obj_size; i++)
84832e05 290 object_base[i] = h->object_base[i];
f65fd747
UD
291
292 /* If the object just copied was the only data in OLD_CHUNK,
293 free that chunk and remove it from the chain.
294 But not if that chunk might contain an empty object. */
6c8dbf00 295 if (!h->maybe_empty_object
2fd4de4b 296 && (h->object_base
b100f9aa
WN
297 == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents,
298 h->alignment_mask)))
f65fd747
UD
299 {
300 new_chunk->prev = old_chunk->prev;
301 CALL_FREEFUN (h, old_chunk);
302 }
303
84832e05 304 h->object_base = object_base;
f65fd747
UD
305 h->next_free = h->object_base + obj_size;
306 /* The new chunk certainly contains no empty object yet. */
307 h->maybe_empty_object = 0;
308}
9d1e2b7d 309# ifdef _LIBC
a20d8dbe 310libc_hidden_def (_obstack_newchunk)
9d1e2b7d 311# endif
f65fd747
UD
312
313/* Return nonzero if object OBJ has been allocated from obstack H.
314 This is here for debugging.
315 If you use it in a program, you are probably losing. */
316
f65fd747
UD
317/* Suppress -Wmissing-prototypes warning. We don't want to declare this in
318 obstack.h because it is just for debugging. */
b100f9aa 319int _obstack_allocated_p (struct obstack *h, void *obj) __attribute_pure__;
f65fd747
UD
320
321int
9d1e2b7d 322_obstack_allocated_p (struct obstack *h, void *obj)
f65fd747 323{
6c8dbf00
OB
324 struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
325 struct _obstack_chunk *plp; /* point to previous chunk if any */
f65fd747
UD
326
327 lp = (h)->chunk;
328 /* We use >= rather than > since the object cannot be exactly at
329 the beginning of the chunk but might be an empty object exactly
330 at the end of an adjacent chunk. */
9d1e2b7d 331 while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
f65fd747
UD
332 {
333 plp = lp->prev;
334 lp = plp;
335 }
336 return lp != 0;
337}
6c8dbf00 338
f65fd747
UD
339/* Free objects in obstack H, including OBJ and everything allocate
340 more recently than OBJ. If OBJ is zero, free everything in H. */
341
647eb037 342# undef obstack_free
f65fd747 343
f65fd747 344void
b100f9aa 345__obstack_free (struct obstack *h, void *obj)
f65fd747 346{
6c8dbf00
OB
347 struct _obstack_chunk *lp; /* below addr of any objects in this chunk */
348 struct _obstack_chunk *plp; /* point to previous chunk if any */
f65fd747
UD
349
350 lp = h->chunk;
351 /* We use >= because there cannot be an object at the beginning of a chunk.
352 But there can be an empty object at that address
353 at the end of another chunk. */
9d1e2b7d 354 while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj))
f65fd747
UD
355 {
356 plp = lp->prev;
357 CALL_FREEFUN (h, lp);
358 lp = plp;
359 /* If we switch chunks, we can't tell whether the new current
b100f9aa 360 chunk contains an empty object, so assume that it may. */
f65fd747
UD
361 h->maybe_empty_object = 1;
362 }
363 if (lp)
364 {
365 h->object_base = h->next_free = (char *) (obj);
366 h->chunk_limit = lp->limit;
367 h->chunk = lp;
368 }
369 else if (obj != 0)
370 /* obj is not in any of the chunks! */
371 abort ();
372}
373
9d1e2b7d
UD
374# ifdef _LIBC
375/* Older versions of libc used a function _obstack_free intended to be
376 called by non-GCC compilers. */
377strong_alias (obstack_free, _obstack_free)
378# endif
6c8dbf00 379
f65fd747 380int
9d1e2b7d 381_obstack_memory_used (struct obstack *h)
f65fd747 382{
6c8dbf00 383 struct _obstack_chunk *lp;
2e09a79a 384 int nbytes = 0;
f65fd747
UD
385
386 for (lp = h->chunk; lp != 0; lp = lp->prev)
387 {
388 nbytes += lp->limit - (char *) lp;
389 }
390 return nbytes;
391}
6c8dbf00 392
f65fd747 393/* Define the error handler. */
9d1e2b7d
UD
394# ifdef _LIBC
395# include <libintl.h>
396# else
397# include "gettext.h"
398# endif
647eb037 399# ifndef _
9d1e2b7d 400# define _(msgid) gettext (msgid)
f65fd747 401# endif
9d1e2b7d 402
230491f0 403# ifdef _LIBC
647eb037 404# include <libio/iolibio.h>
647eb037 405# endif
f65fd747 406
b100f9aa 407static _Noreturn void
9d1e2b7d 408print_and_abort (void)
f65fd747 409{
59adeb11
UD
410 /* Don't change any of these strings. Yes, it would be possible to add
411 the newline to the string and use fputs or so. But this must not
412 happen because the "memory exhausted" message appears in other places
413 like this and the translation should be reused instead of creating
414 a very similar string which requires a separate translation. */
2fd4de4b 415# ifdef _LIBC
b100f9aa 416 (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
2fd4de4b 417# else
b100f9aa 418 fprintf (stderr, "%s\n", _("memory exhausted"));
2fd4de4b 419# endif
f65fd747
UD
420 exit (obstack_exit_failure);
421}
b100f9aa 422
6c8dbf00 423#endif /* !ELIDE_CODE */