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  <br...@clisp.org>

        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,




Reply via email to