Paul Eggert wrote:
> > Do you see a problem with fixing these things? May I go ahead and modernize
> > this?
> 
> No, please feel free, and thanks.

This patch should fix all mentioned problems.


2023-11-15  Bruno Haible  <[email protected]>

        obstack: Modernize, fixing several problems.
        * lib/obstack.in.h: Renamed from lib/obstack.h. Add reference to the
        glibc documentation.
        (_OBSTACK_INTERFACE_VERSION): Remove macro.
        (_OBSTACK_SIZE_T, _CHUNK_SIZE_T, _OBSTACK_CAST): Mark old values with
        _LIBC.
        (_obstack_newchunk, _obstack_free, _obstack_begin, _obstack_begin_1,
        _obstack_memory_used, _obstack_allocated_p): Override if REPLACE_OBSTACK
        is 1.
        * lib/obstack.c: Don't include <gnu-versions.h>.
        (_OBSTACK_ELIDE_CODE): Remove macro.
        * m4/obstack.m4 (gl_FUNC_OBSTACK): Test whether obstack.h exists. Don't
        define HAVE_OBSTACK any more. Set HAVE_OBSTACK, REPLACE_OBSTACK,
        GL_GENERATE_OBSTACK_H.
        * modules/obstack (Files): Remove obstack.h. Add obstack.in.h.
        (Depends-on): Add gen-header. Add conditions.
        (configure.ac): Consider HAVE_OBSTACK, REPLACE_OBSTACK. Invoke
        gl_CONDITIONAL_HEADER and AC_PROG_MKDIR_P.
        (Makefile.am): Generate obstack.h. Augment BUILT_SOURCES and
        MOSTLYCLEANFILES.

>From 5657476a730c6dc296c6d4a3ab239ba7ef339fad Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Thu, 16 Nov 2023 00:09:40 +0100
Subject: [PATCH] obstack: Modernize, fixing several problems.

* lib/obstack.in.h: Renamed from lib/obstack.h. Add reference to the
glibc documentation.
(_OBSTACK_INTERFACE_VERSION): Remove macro.
(_OBSTACK_SIZE_T, _CHUNK_SIZE_T, _OBSTACK_CAST): Mark old values with
_LIBC.
(_obstack_newchunk, _obstack_free, _obstack_begin, _obstack_begin_1,
_obstack_memory_used, _obstack_allocated_p): Override if REPLACE_OBSTACK
is 1.
* lib/obstack.c: Don't include <gnu-versions.h>.
(_OBSTACK_ELIDE_CODE): Remove macro.
* m4/obstack.m4 (gl_FUNC_OBSTACK): Test whether obstack.h exists. Don't
define HAVE_OBSTACK any more. Set HAVE_OBSTACK, REPLACE_OBSTACK,
GL_GENERATE_OBSTACK_H.
* modules/obstack (Files): Remove obstack.h. Add obstack.in.h.
(Depends-on): Add gen-header. Add conditions.
(configure.ac): Consider HAVE_OBSTACK, REPLACE_OBSTACK. Invoke
gl_CONDITIONAL_HEADER and AC_PROG_MKDIR_P.
(Makefile.am): Generate obstack.h. Augment BUILT_SOURCES and
MOSTLYCLEANFILES.
---
 ChangeLog                       | 23 +++++++++
 lib/obstack.c                   | 91 +++++++++++++--------------------
 lib/{obstack.h => obstack.in.h} | 26 ++++++----
 m4/obstack.m4                   | 53 ++++++++++++-------
 modules/obstack                 | 35 ++++++++++---
 5 files changed, 136 insertions(+), 92 deletions(-)
 rename lib/{obstack.h => obstack.in.h} (97%)

diff --git a/ChangeLog b/ChangeLog
index 16dbb4240c..9132fef875 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2023-11-15  Bruno Haible  <[email protected]>
+
+	obstack: Modernize, fixing several problems.
+	* lib/obstack.in.h: Renamed from lib/obstack.h. Add reference to the
+	glibc documentation.
+	(_OBSTACK_INTERFACE_VERSION): Remove macro.
+	(_OBSTACK_SIZE_T, _CHUNK_SIZE_T, _OBSTACK_CAST): Mark old values with
+	_LIBC.
+	(_obstack_newchunk, _obstack_free, _obstack_begin, _obstack_begin_1,
+	_obstack_memory_used, _obstack_allocated_p): Override if REPLACE_OBSTACK
+	is 1.
+	* lib/obstack.c: Don't include <gnu-versions.h>.
+	(_OBSTACK_ELIDE_CODE): Remove macro.
+	* m4/obstack.m4 (gl_FUNC_OBSTACK): Test whether obstack.h exists. Don't
+	define HAVE_OBSTACK any more. Set HAVE_OBSTACK, REPLACE_OBSTACK,
+	GL_GENERATE_OBSTACK_H.
+	* modules/obstack (Files): Remove obstack.h. Add obstack.in.h.
+	(Depends-on): Add gen-header. Add conditions.
+	(configure.ac): Consider HAVE_OBSTACK, REPLACE_OBSTACK. Invoke
+	gl_CONDITIONAL_HEADER and AC_PROG_MKDIR_P.
+	(Makefile.am): Generate obstack.h. Augment BUILT_SOURCES and
+	MOSTLYCLEANFILES.
+
 2023-11-15  Paul Eggert  <[email protected]>
 
 	striconveha: pacify gcc -Wcast-align
diff --git a/lib/obstack.c b/lib/obstack.c
index ca2e61c8cc..99cee94ede 100644
--- a/lib/obstack.c
+++ b/lib/obstack.c
@@ -23,43 +23,23 @@
 # include "obstack.h"
 #endif
 
-/* NOTE BEFORE MODIFYING THIS FILE: _OBSTACK_INTERFACE_VERSION in
-   obstack.h must be incremented whenever callers compiled using an old
+/* NOTE BEFORE MODIFYING THIS FILE IN GNU LIBC: _OBSTACK_INTERFACE_VERSION in
+   gnu-versions.h must be incremented whenever callers compiled using an old
    obstack.h can no longer properly call the functions in this file.  */
 
-/* Comment out all this code if we are using the GNU C Library, and are not
-   actually compiling the library itself, and the installed library
-   supports the same library interface we do.  This code is part of the GNU
-   C Library, but also included in many other GNU distributions.  Compiling
-   and linking in this code is a waste when using the GNU C library
-   (especially if it is a shared library).  Rather than having every GNU
-   program understand 'configure --with-gnu-libc' and omit the object
-   files, it is simpler to just do this in the source for each such file.  */
-#if !defined _LIBC && defined __GNU_LIBRARY__ && __GNU_LIBRARY__ > 1
-# include <gnu-versions.h>
-# if (_GNU_OBSTACK_INTERFACE_VERSION == _OBSTACK_INTERFACE_VERSION	      \
-      || (_GNU_OBSTACK_INTERFACE_VERSION == 1				      \
-          && _OBSTACK_INTERFACE_VERSION == 2				      \
-          && defined SIZEOF_INT && defined SIZEOF_SIZE_T		      \
-          && SIZEOF_INT == SIZEOF_SIZE_T))
-#  define _OBSTACK_ELIDE_CODE
-# endif
-#endif
-
-#ifndef _OBSTACK_ELIDE_CODE
 /* If GCC, or if an oddball (testing?) host that #defines __alignof__,
    use the already-supplied __alignof__.  Otherwise, this must be Gnulib
    (as glibc assumes GCC); defer to Gnulib's alignof_type.  */
-# if !defined __GNUC__ && !defined __alignof__
-#  include <alignof.h>
-#  define __alignof__(type) alignof_type (type)
-# endif
-# include <stdlib.h>
-# include <stdint.h>
+#if !defined __GNUC__ && !defined __alignof__
+# include <alignof.h>
+# define __alignof__(type) alignof_type (type)
+#endif
+#include <stdlib.h>
+#include <stdint.h>
 
-# ifndef MAX
-#  define MAX(a,b) ((a) > (b) ? (a) : (b))
-# endif
+#ifndef MAX
+# define MAX(a,b) ((a) > (b) ? (a) : (b))
+#endif
 
 /* Determine default alignment.  */
 
@@ -300,30 +280,30 @@ _obstack_memory_used (struct obstack *h)
   return nbytes;
 }
 
-# ifndef _OBSTACK_NO_ERROR_HANDLER
+#ifndef _OBSTACK_NO_ERROR_HANDLER
 /* Define the error handler.  */
-#  include <stdio.h>
+# include <stdio.h>
 
 /* Exit value used when 'print_and_abort' is used.  */
-#  ifdef _LIBC
+# ifdef _LIBC
 int obstack_exit_failure = EXIT_FAILURE;
-#  else
-#   include "exitfail.h"
-#   define obstack_exit_failure exit_failure
-#  endif
-
-#  ifdef _LIBC
-#   include <libintl.h>
-#  else
-#   include "gettext.h"
-#  endif
-#  ifndef _
-#   define _(msgid) gettext (msgid)
-#  endif
-
-#  ifdef _LIBC
-#   include <libio/iolibio.h>
-#  endif
+# else
+#  include "exitfail.h"
+#  define obstack_exit_failure exit_failure
+# endif
+
+# ifdef _LIBC
+#  include <libintl.h>
+# else
+#  include "gettext.h"
+# endif
+# ifndef _
+#  define _(msgid) gettext (msgid)
+# endif
+
+# ifdef _LIBC
+#  include <libio/iolibio.h>
+# endif
 
 static __attribute_noreturn__ void
 print_and_abort (void)
@@ -333,11 +313,11 @@ print_and_abort (void)
      happen because the "memory exhausted" message appears in other places
      like this and the translation should be reused instead of creating
      a very similar string which requires a separate translation.  */
-#  ifdef _LIBC
+# ifdef _LIBC
   (void) __fxprintf (NULL, "%s\n", _("memory exhausted"));
-#  else
+# else
   fprintf (stderr, "%s\n", _("memory exhausted"));
-#  endif
+# endif
   exit (obstack_exit_failure);
 }
 
@@ -349,5 +329,4 @@ print_and_abort (void)
    'print_and_abort'.  */
 __attribute_noreturn__ void (*obstack_alloc_failed_handler) (void)
   = print_and_abort;
-# endif /* !_OBSTACK_NO_ERROR_HANDLER */
-#endif /* !_OBSTACK_ELIDE_CODE */
+#endif /* !_OBSTACK_NO_ERROR_HANDLER */
diff --git a/lib/obstack.h b/lib/obstack.in.h
similarity index 97%
rename from lib/obstack.h
rename to lib/obstack.in.h
index cb080c33b5..265203b6e2 100644
--- a/lib/obstack.h
+++ b/lib/obstack.in.h
@@ -97,9 +97,11 @@
           as you would with a stack.)
  */
 
+/* Documentation (part of the GNU libc manual):
+   <https://www.gnu.org/software/libc/manual/html_node/Obstacks.html>  */
 
-/* Don't do the contents of this file more than once.  */
 
+/* Don't do the contents of this file more than once.  */
 #ifndef _OBSTACK_H
 #define _OBSTACK_H 1
 
@@ -108,12 +110,8 @@
  #error "Please include config.h first."
 #endif
 
-#ifndef _OBSTACK_INTERFACE_VERSION
-# define _OBSTACK_INTERFACE_VERSION 2
-#endif
-
 #include <stddef.h>             /* For size_t and ptrdiff_t.  */
-#include <string.h>             /* For __GNU_LIBRARY__, and memcpy.  */
+#include <string.h>             /* For memcpy.  */
 
 #if __STDC_VERSION__ < 199901L || defined __HP_cc
 # define __FLEXIBLE_ARRAY_MEMBER 1
@@ -121,14 +119,14 @@
 # define __FLEXIBLE_ARRAY_MEMBER
 #endif
 
-#if _OBSTACK_INTERFACE_VERSION == 1
-/* For binary compatibility with obstack version 1, which used "int"
-   and "long" for these two types.  */
+/* These macros highlight the places where this implementation
+   is different from the one in GNU libc.  */
+#ifdef _LIBC
 # define _OBSTACK_SIZE_T unsigned int
 # define _CHUNK_SIZE_T unsigned long
 # define _OBSTACK_CAST(type, expr) ((type) (expr))
 #else
-/* Version 2 with sane types, especially for 64-bit hosts.  */
+/* In Gnulib, we use sane types, especially for 64-bit hosts.  */
 # define _OBSTACK_SIZE_T size_t
 # define _CHUNK_SIZE_T size_t
 # define _OBSTACK_CAST(type, expr) (expr)
@@ -214,6 +212,14 @@ struct obstack          /* control current object in current chunk */
 
 /* Declare the external functions we use; they are in obstack.c.  */
 
+#if @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
+#endif
 extern void _obstack_newchunk (struct obstack *, _OBSTACK_SIZE_T);
 extern void _obstack_free (struct obstack *, void *);
 extern int _obstack_begin (struct obstack *,
diff --git a/m4/obstack.m4 b/m4/obstack.m4
index ef70a52093..88a3f3a0e0 100644
--- a/m4/obstack.m4
+++ b/m4/obstack.m4
@@ -10,24 +10,39 @@
 
 AC_DEFUN([gl_FUNC_OBSTACK],
 [
-  AC_CACHE_CHECK([for obstacks that work with any size object],
-    [gl_cv_func_obstack],
-    [AC_LINK_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include "obstack.h"
-            void *obstack_chunk_alloc (size_t n) { return 0; }
-            void obstack_chunk_free (void *p) { }
-            /* Check that an internal function returns size_t, not int.  */
-            size_t _obstack_memory_used (struct obstack *);
-           ]],
-          [[struct obstack mem;
-            obstack_init (&mem);
-            obstack_free (&mem, 0);
-          ]])],
-       [gl_cv_func_obstack=yes],
-       [gl_cv_func_obstack=no])])
-  if test "$gl_cv_func_obstack" = yes; then
-    AC_DEFINE([HAVE_OBSTACK], 1,
-      [Define to 1 if the system has obstacks that work with any size object.])
+  AC_CHECK_HEADERS_ONCE([obstack.h])
+  if test $ac_cv_header_obstack_h = yes; then
+    HAVE_OBSTACK=1
+    AC_CACHE_CHECK([for obstacks that work with any size object],
+      [gl_cv_func_obstack],
+      [AC_LINK_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include "obstack.h"
+              void *obstack_chunk_alloc (size_t n) { return 0; }
+              void obstack_chunk_free (void *p) { }
+              /* Check that an internal function returns size_t, not int.  */
+              size_t _obstack_memory_used (struct obstack *);
+             ]],
+            [[struct obstack mem;
+              obstack_init (&mem);
+              obstack_free (&mem, 0);
+            ]])],
+         [gl_cv_func_obstack=yes],
+         [gl_cv_func_obstack=no])
+      ])
+    if test $gl_cv_func_obstack = yes; then
+      REPLACE_OBSTACK=0
+    else
+      REPLACE_OBSTACK=1
+    fi
+  else
+    HAVE_OBSTACK=0
+    REPLACE_OBSTACK=0
   fi
+  if test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1; then
+    GL_GENERATE_OBSTACK_H=true
+  else
+    GL_GENERATE_OBSTACK_H=false
+  fi
+  AC_SUBST([REPLACE_OBSTACK])
 ])
diff --git a/modules/obstack b/modules/obstack
index 98bca67e1e..e4db4cdc97 100644
--- a/modules/obstack
+++ b/modules/obstack
@@ -2,22 +2,43 @@ Description:
 Memory allocation, optimized for stack-like allocation patterns.
 
 Files:
-lib/obstack.h
+lib/obstack.in.h
 lib/obstack.c
 m4/obstack.m4
 
 Depends-on:
-alignof
-gettext-h
-exitfail
-stdint
-stdlib
+gen-header
+alignof         [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1]
+gettext-h       [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1]
+exitfail        [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1]
+stdint          [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1]
+stdlib          [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1]
 
 configure.ac:
 gl_FUNC_OBSTACK
-gl_CONDITIONAL([GL_COND_OBJ_OBSTACK], [test "$gl_cv_func_obstack" != yes])
+gl_CONDITIONAL_HEADER([obstack.h])
+gl_CONDITIONAL([GL_COND_OBJ_OBSTACK],
+               [test $HAVE_OBSTACK = 0 || test $REPLACE_OBSTACK = 1])
+AC_PROG_MKDIR_P
 
 Makefile.am:
+BUILT_SOURCES += $(OBSTACK_H)
+
+# We need the following in order to create <obstack.h> when the system
+# doesn't have one that works with any size object.
+if GL_GENERATE_OBSTACK_H
+obstack.h: obstack.in.h $(top_builddir)/config.status
+@NMD@	$(AM_V_GEN)$(MKDIR_P) '%reldir%'
+	$(gl_V_at)$(SED_HEADER_STDOUT) \
+	      -e 's|@''REPLACE_OBSTACK''@|$(REPLACE_OBSTACK)|g' \
+	      $(srcdir)/obstack.in.h > $@-t
+	$(AM_V_at)mv $@-t $@
+else
+obstack.h: $(top_builddir)/config.status
+	rm -f $@
+endif
+MOSTLYCLEANFILES += obstack.h obstack.h-t
+
 if GL_COND_OBJ_OBSTACK
 lib_SOURCES += obstack.c
 endif
-- 
2.34.1

Reply via email to