Paul Eggert wrote:
> diff --git a/lib/obstack.c b/lib/obstack.c
> index b5cf0d514b..9877207cb1 100644
> --- a/lib/obstack.c
> +++ b/lib/obstack.c
> @@ -250,8 +250,10 @@ _obstack_allocated_p (struct obstack *h, void *obj)
> /* Free objects in obstack H, including OBJ and everything allocate
> more recently than OBJ. If OBJ is zero, free everything in H. */
>
> +#undef obstack_free
> +
> void
This #undef breaks library namespacing.
How to reproduce:
On a platform without obstack in libc, say, FreeBSD, define
CPPFLAGS=-D_obstack_free=libfoo_obstack_free
-Dobstack_free=libfoo_obstack_free
-D_obstack_allocated_p=libfoo_obstack_allocated_p
-D_obstack_begin=libfoo_obstack_begin -D_obstack_begin_1=libfoo_obstack_begin_1
-D_obstack_memory_used=libfoo_obstack_memory_used
-D_obstack_newchunk=libfoo_obstack_newchunk"
and compile a testdir of module 'obstack':
$ ./configure
$ make
$ nm gllib/obstack.o
Before your patch series, the result was
U __stderrp
U abort
U exit
U exit_failure
U fprintf
0000000000000250 T libfoo_obstack_allocated_p
0000000000000000 T libfoo_obstack_begin
0000000000000090 T libfoo_obstack_begin_1
0000000000000280 T libfoo_obstack_free
0000000000000300 T libfoo_obstack_memory_used
0000000000000120 T libfoo_obstack_newchunk
U memcpy
0000000000000000 D obstack_alloc_failed_handler
0000000000000330 t print_and_abort
that is, all 'T' symbols prefixed with 'libfoo_'.
Whereas now, the result is
U __stderrp
U abort
U exit
U exit_failure
U fprintf
0000000000000370 T libfoo_obstack_allocated_p
0000000000000030 T libfoo_obstack_begin
0000000000000120 T libfoo_obstack_begin_1
0000000000000420 T libfoo_obstack_memory_used
0000000000000210 T libfoo_obstack_newchunk
U memcpy
0000000000000000 D obstack_alloc_failed_handler
00000000000003a0 T obstack_free
0000000000000000 t print_and_abort
that is, 'obstack_free' is not namespaced.
Simply moving the #undef to line 323 does not work, because it produces
a conflict between the macro 'obstack_free' (defined in obstack.h) and
the function definition of 'obstack_free' in obstack.c.
But the attached patch fixes it. It produces this symbol list:
U __stderrp
U abort
U exit
U exit_failure
U fprintf
0000000000000370 T libfoo_obstack_allocated_p
0000000000000030 T libfoo_obstack_begin
0000000000000120 T libfoo_obstack_begin_1
00000000000003a0 T libfoo_obstack_free
0000000000000420 T libfoo_obstack_memory_used
0000000000000210 T libfoo_obstack_newchunk
U memcpy
0000000000000000 D obstack_alloc_failed_handler
0000000000000000 t print_and_abort
After this patch, what is the remaining purpose of using '__obstack_free'?
Why not get back to '_obstack_free'? Your ChangeLog entry says
"This is for compatibility with glibc, which in turn is for compatibility
with old Gnulib." The comment in glibc says
/* The default name of the function for freeing a chunk is 'obstack_free',
but gnulib users can override this by defining '__obstack_free'. */
but in fact no package does this. Search
https://codesearch.debian.net/search?q=define+__obstack_free&literal=1
https://codesearch.debian.net/search?q=D__obstack_free%3D&literal=1
Maybe there were packages who used this way of customizing __obstack_free
twenty years ago. But they can use obstack_specify_allocation or
obstack_specify_allocation_1, like everyone else:
https://codesearch.debian.net/search?q=obstack_specify_allocation+%28&literal=1
2025-05-06 Bruno Haible <[email protected]>
obstack: Fix library namespacing (regression yesterday).
* lib/obstack.in.h (__obstack_free): Define to _obstack_free, not
obstack_free, within glibc and in gnulib on systems without glibc.
* lib/obstack.c (obstack_free): Undefine only for the strong_alias.
(obstack_free): Define as an alias of _obstack_free, not vice versa.
diff --git a/lib/obstack.c b/lib/obstack.c
index 9c15886717..8346c898ea 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -288,8 +288,6 @@ _obstack_allocated_p (struct obstack *h, void *obj)
/* Free objects in obstack H, including OBJ and everything allocate
more recently than OBJ. If OBJ is zero, free everything in H. */
-#undef obstack_free
-
void
__obstack_free (struct obstack *h, void *obj)
{
@@ -322,7 +320,8 @@ __obstack_free (struct obstack *h, void *obj)
/* Older versions of libc used a function _obstack_free intended to be
called by non-GCC compilers. */
-strong_alias (obstack_free, _obstack_free)
+#undef obstack_free
+strong_alias (_obstack_free, obstack_free)
_OBSTACK_INDEX_T
_obstack_memory_used (struct obstack *h)
diff --git a/lib/obstack.in.h b/lib/obstack.in.h
index d5a0ceff6d..85252ff430 100644
--- a/lib/obstack.in.h
+++ b/lib/obstack.in.h
@@ -233,16 +233,23 @@ struct obstack /* control current object in
current chunk */
/* Declare the external functions we use; they are in obstack.c. */
-#if defined __GL_REPLACE_OBSTACK__
-# define _obstack_newchunk rpl_obstack_newchunk
-# define __obstack_free rpl_obstack_free
-# define _obstack_begin rpl_obstack_begin
-# define _obstack_begin_1 rpl_obstack_begin_1
-# define _obstack_memory_used rpl_obstack_memory_used
-# define _obstack_allocated_p rpl_obstack_allocated_p
-#elif !defined __obstack_free /* for old Gnulib */
-# define __obstack_free obstack_free
+#if defined __GL_GNULIB_HEADER
+/* Symbol mapping for gnulib. */
+# if defined __GL_REPLACE_OBSTACK__
+# define _obstack_newchunk rpl_obstack_newchunk
+# define __obstack_free rpl_obstack_free
+# define _obstack_begin rpl_obstack_begin
+# define _obstack_begin_1 rpl_obstack_begin_1
+# define _obstack_memory_used rpl_obstack_memory_used
+# define _obstack_allocated_p rpl_obstack_allocated_p
+# else
+# define __obstack_free _obstack_free
+# endif
+#else
+/* Symbol mapping for glibc. */
+# define __obstack_free _obstack_free
#endif
+
extern void _obstack_newchunk (struct obstack *, _OBSTACK_INDEX_T);
extern int _obstack_begin (struct obstack *,
_OBSTACK_INDEX_T, _OBSTACK_INDEX_T,