+2023-11-15 Bruno Haible <bruno@clisp.org>
+
+ 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 <eggert@cs.ucla.edu>
striconveha: pacify gcc -Wcast-align
# 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. */
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)
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);
}
'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 */
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
#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
# 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)
/* 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 *,
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])
])
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