* lib/error.c: Merge changes since 2018 from glibc.
----- The following changes are taken from glibc:
(__error_internal, __error_at_line_internal): New functions,
with most of the old error and error_at_line_internal but
with va_list and with a new trailing mode_args,
for wide character mode.
(error_tail): Add trailing arg.
(error_tail, __error_internal, __error_at_line_internal):
Redo _LIBC implementation with respect to cancelation.
[_LIBC]: Include <libc-lock.h>, not <bits/libc-lock.h>.
----- The following changes are specific to Gnulib:
(__error_internal, __error_at_line_internal, error_tail) [!_LIBC]:
Use macros to define away the new trailing arg, and to name
the internal functions to verror and verror_at_line.
(verror, verror_at_line) [!_LIBC]: Undef so that we omit
the __gl_error_call business when defining these functions.
* lib/error.in.h: Include stdarg.h.
(verror, verror_at_line): New decls and macros.
* m4/error_h.m4 ([gl_ERROR_H]): Always compile error.c if
the verror module is also present.
* modules/verror (Files, lib_SOURCES):
Remove lib/verror.h, lib/verror.c.
(Depends-on): Remove stdio, xvasprintf.
(configure.ac-early): Define gl_HAVE_MODULE_VERROR so that
the error module compiles error.c. Not sure if this is the
standard way to do this, but it seems to work.
* modules/verror (Include), tests/test-verror.c:
Include error.h, not verror.h.
2024-08-14 Paul Eggert <eggert@cs.ucla.edu>
+ error: merge from glibc and with verror
+ * lib/error.c: Merge changes since 2018 from glibc.
+ ----- The following changes are taken from glibc:
+ (__error_internal, __error_at_line_internal): New functions,
+ with most of the old error and error_at_line_internal but
+ with va_list and with a new trailing mode_args,
+ for wide character mode.
+ (error_tail): Add trailing arg.
+ (error_tail, __error_internal, __error_at_line_internal):
+ Redo _LIBC implementation with respect to cancelation.
+ [_LIBC]: Include <libc-lock.h>, not <bits/libc-lock.h>.
+ ----- The following changes are specific to Gnulib:
+ (__error_internal, __error_at_line_internal, error_tail) [!_LIBC]:
+ Use macros to define away the new trailing arg, and to name
+ the internal functions to verror and verror_at_line.
+ (verror, verror_at_line) [!_LIBC]: Undef so that we omit
+ the __gl_error_call business when defining these functions.
+ * lib/error.in.h: Include stdarg.h.
+ (verror, verror_at_line): New decls and macros.
+ * m4/error_h.m4 ([gl_ERROR_H]): Always compile error.c if
+ the verror module is also present.
+ * modules/verror (Files, lib_SOURCES):
+ Remove lib/verror.h, lib/verror.c.
+ (Depends-on): Remove stdio, xvasprintf.
+ (configure.ac-early): Define gl_HAVE_MODULE_VERROR so that
+ the error module compiles error.c. Not sure if this is the
+ standard way to do this, but it seems to work.
+ * modules/verror (Include), tests/test-verror.c:
+ Include error.h, not verror.h.
+
error: it’s cold
This mimics what glibc is doing nowadays.
* lib/error.in.h (error, error_at_line):
Date Modules Changes
+2024-08-14 verror The include file is changed from "verror.h"
+ to <error.h>.
+
2024-08-09 full-read These modules now prefer signed types to size_t.
full-write The preferred types are idx_t for object sizes and
safe-read ptrdiff_t for values that are either a size or -1.
/* Error handler for noninteractive utilities
- Copyright (C) 1990-1998, 2000-2007, 2009-2024 Free Software Foundation, Inc.
+ Copyright (C) 1990-2024 Free Software Foundation, Inc.
This file is part of the GNU C Library.
- This file is free software: you can redistribute it and/or modify
- it under the terms of the GNU Lesser General Public License as
- published by the Free Software Foundation; either version 2.1 of the
- License, or (at your option) any later version.
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
- This file is distributed in the hope that it will be useful,
+ The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Lesser General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */
#if !_LIBC
# include <config.h>
# define _GL_NO_INLINE_ERROR
+# define __error_internal(status, err, fmt, args, flags) \
+ verror (status, err, fmt, args)
+# define __error_at_line_internal(status, err, file, line, fmt, args, flags) \
+ verror_at_line (status, err, file, line, fmt, args)
+# define error_tail(status, err, fmt, args, flags) \
+ error_tail (status, err, fmt, args)
#endif
#include <error.h>
# undef putc
# define putc(c, fp) _IO_putc (c, fp)
-# include <bits/libc-lock.h>
+# include <libc-lock.h>
#else /* not _LIBC */
# if GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r
# define __strerror_r strerror_r
# endif /* GNULIB_STRERROR_R_POSIX || HAVE_STRERROR_R || defined strerror_r */
+
+# undef verror
+# undef verror_at_line
#endif /* not _LIBC */
#if !_LIBC
}
static void _GL_ATTRIBUTE_FORMAT_PRINTF_STANDARD (3, 0) _GL_ARG_NONNULL ((3))
-error_tail (int status, int errnum, const char *message, va_list args)
+error_tail (int status, int errnum, const char *message, va_list args,
+ unsigned int mode_flags)
{
#if _LIBC
- if (_IO_fwide (stderr, 0) > 0)
- {
- size_t len = strlen (message) + 1;
- wchar_t *wmessage = NULL;
- mbstate_t st;
- size_t res;
- const char *tmp;
- bool use_malloc = false;
-
- while (1)
- {
- if (__libc_use_alloca (len * sizeof (wchar_t)))
- wmessage = (wchar_t *) alloca (len * sizeof (wchar_t));
- else
- {
- if (!use_malloc)
- wmessage = NULL;
-
- wchar_t *p = (wchar_t *) realloc (wmessage,
- len * sizeof (wchar_t));
- if (p == NULL)
- {
- free (wmessage);
- fputws_unlocked (L"out of memory\n", stderr);
- return;
- }
- wmessage = p;
- use_malloc = true;
- }
-
- memset (&st, '\0', sizeof (st));
- tmp = message;
-
- res = mbsrtowcs (wmessage, &tmp, len, &st);
- if (res != len)
- break;
-
- if (__builtin_expect (len >= SIZE_MAX / sizeof (wchar_t) / 2, 0))
- {
- /* This really should not happen if everything is fine. */
- res = (size_t) -1;
- break;
- }
-
- len *= 2;
- }
-
- if (res == (size_t) -1)
- {
- /* The string cannot be converted. */
- if (use_malloc)
- {
- free (wmessage);
- use_malloc = false;
- }
- wmessage = (wchar_t *) L"???";
- }
-
- __vfwprintf (stderr, wmessage, args);
-
- if (use_malloc)
- free (wmessage);
- }
- else
+ int ret = __vfxprintf (stderr, message, args, mode_flags);
+ if (ret < 0 && errno == ENOMEM && _IO_fwide (stderr, 0) > 0)
+ /* Leave a trace in case the heap allocation of the message string
+ failed. */
+ fputws_unlocked (L"out of memory\n", stderr);
+#else
+ vfprintf (stderr, message, args);
#endif
- vfprintf (stderr, message, args);
+ va_end (args);
++error_message_count;
if (errnum)
If ERRNUM is nonzero, print its corresponding system error message.
Exit with status STATUS if it is nonzero. */
void
-error (int status, int errnum, const char *message, ...)
+__error_internal (int status, int errnum, const char *message,
+ va_list args, unsigned int mode_flags)
{
- va_list args;
-
-#if defined _LIBC && defined __libc_ptf_call
+#if defined _LIBC
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
- __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
- 0);
+ __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
#endif
flush_stdout ();
#endif
}
- va_start (args, message);
- error_tail (status, errnum, message, args);
- va_end (args);
+ error_tail (status, errnum, message, args, mode_flags);
#ifdef _LIBC
_IO_funlockfile (stderr);
-# ifdef __libc_ptf_call
- __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
-# endif
+ __pthread_setcancelstate (state, NULL);
#endif
}
+
+void
+error (int status, int errnum, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ __error_internal (status, errnum, message, ap, 0);
+ va_end (ap);
+}
\f
/* Sometimes we want to have at most one error per line. This
variable controls whether this mode is selected or not. */
int error_one_per_line;
void
-error_at_line (int status, int errnum, const char *file_name,
- unsigned int line_number, const char *message, ...)
+__error_at_line_internal (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message,
+ va_list args, unsigned int mode_flags)
{
- va_list args;
-
if (error_one_per_line)
{
static const char *old_file_name;
old_line_number = line_number;
}
-#if defined _LIBC && defined __libc_ptf_call
+#if defined _LIBC
/* We do not want this call to be cut short by a thread
cancellation. Therefore disable cancellation for now. */
int state = PTHREAD_CANCEL_ENABLE;
- __libc_ptf_call (pthread_setcancelstate, (PTHREAD_CANCEL_DISABLE, &state),
- 0);
+ __pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &state);
#endif
flush_stdout ();
file_name, line_number);
#endif
- va_start (args, message);
- error_tail (status, errnum, message, args);
- va_end (args);
+ error_tail (status, errnum, message, args, mode_flags);
#ifdef _LIBC
_IO_funlockfile (stderr);
-# ifdef __libc_ptf_call
- __libc_ptf_call (pthread_setcancelstate, (state, NULL), 0);
-# endif
+ __pthread_setcancelstate (state, NULL);
#endif
}
+void
+error_at_line (int status, int errnum, const char *file_name,
+ unsigned int line_number, const char *message, ...)
+{
+ va_list ap;
+ va_start (ap, message);
+ __error_at_line_internal (status, errnum, file_name, line_number,
+ message, ap, 0);
+ va_end (ap);
+}
+
#ifdef _LIBC
/* Make the weak alias. */
# undef error
#error "Please include config.h first."
#endif
+/* Get va_list. */
+#include <stdarg.h>
+
/* Get 'unreachable'. */
#include <stddef.h>
#endif
_GL_CXXALIASWARN (error_at_line);
+/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
+ if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+ If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
+ Use the globals error_print_progname and error_message_count similarly
+ to error(). */
+
+extern void verror (int __status, int __errnum, const char *__format,
+ va_list __args)
+ _GL_ATTRIBUTE_COLD
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
+#define verror(status, ...) \
+ __gl_error_call (verror, status, __VA_ARGS__)
+
+/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
+ if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+ If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
+ If FNAME is not NULL, prepend the message with "FNAME:LINENO:".
+ Use the globals error_print_progname, error_message_count, and
+ error_one_per_line similarly to error_at_line(). */
+
+extern void verror_at_line (int __status, int __errnum, const char *__fname,
+ unsigned int __lineno, const char *__format,
+ va_list __args)
+ _GL_ATTRIBUTE_COLD
+ _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 5, 0));
+#define verror_at_line(status, ...) \
+ __gl_error_call (verror_at_line, status, __VA_ARGS__)
+
/* If NULL, error will flush stdout, then print on stderr the program
name, a colon and a space. Otherwise, error will call this
function without parameters instead. */
+++ /dev/null
-/* va_list error handler for noninteractive utilities
- Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-/* Written by Eric Blake. */
-
-#include <config.h>
-
-/* Specification. */
-#include "verror.h"
-
-#include <errno.h>
-#include <stdarg.h>
-#include <stdlib.h>
-
-#include <error.h>
-#include "xvasprintf.h"
-
-#if ENABLE_NLS
-# include "gettext.h"
-# define _(msgid) gettext (msgid)
-#endif
-
-#ifndef _
-# define _(String) String
-#endif
-
-/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
- if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
- If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
- Use the globals error_print_progname and error_message_count similarly
- to error(). */
-void
-verror (int status, int errnum, const char *format, va_list args)
-{
- verror_at_line (status, errnum, NULL, 0, format, args);
-}
-
-/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
- if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
- If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
- If FNAME is not NULL, prepend the message with "FNAME:LINENO:".
- Use the globals error_print_progname, error_message_count, and
- error_one_per_line similarly to error_at_line(). */
-void
-verror_at_line (int status, int errnum, const char *file,
- unsigned int line_number, const char *format, va_list args)
-{
- char *message = xvasprintf (format, args);
- if (message)
- {
- /* Until https://sourceware.org/bugzilla/show_bug.cgi?id=2997 is fixed,
- glibc violates GNU Coding Standards when the file argument to
- error_at_line is NULL. */
- if (file)
- error_at_line (status, errnum, file, line_number, "%s", message);
- else
- error (status, errnum, "%s", message);
- }
- else
- {
- /* EOVERFLOW, EINVAL, and EILSEQ from xvasprintf are signs of
- serious programmer errors. */
- error (0, errno, _("unable to display error message"));
- abort ();
- }
- free (message);
-}
+++ /dev/null
-/* Declaration for va_list error-reporting function
- Copyright (C) 2006-2007, 2009-2024 Free Software Foundation, Inc.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>. */
-
-#ifndef _VERROR_H
-#define _VERROR_H 1
-
-/* This file uses _GL_ATTRIBUTE_COLD, _GL_ATTRIBUTE_FORMAT. */
-#if !_GL_CONFIG_H_INCLUDED
- #error "Please include config.h first."
-#endif
-
-#include <stdarg.h>
-
-/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD. */
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
- if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
- If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
- Use the globals error_print_progname and error_message_count similarly
- to error(). */
-
-extern void verror (int __status, int __errnum, const char *__format,
- va_list __args)
- _GL_ATTRIBUTE_COLD
- _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 0));
-
-/* Print a message with 'vfprintf (stderr, FORMAT, ARGS)';
- if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
- If STATUS is nonzero, terminate the program with 'exit (STATUS)'.
- If FNAME is not NULL, prepend the message with "FNAME:LINENO:".
- Use the globals error_print_progname, error_message_count, and
- error_one_per_line similarly to error_at_line(). */
-
-extern void verror_at_line (int __status, int __errnum, const char *__fname,
- unsigned int __lineno, const char *__format,
- va_list __args)
- _GL_ATTRIBUTE_COLD
- _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 5, 0));
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* verror.h */
# error_h.m4
-# serial 4
+# serial 5
dnl Copyright (C) 1996-2024 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
esac
fi
- if test $HAVE_ERROR = 0 || test $REPLACE_ERROR = 1 \
- || test $HAVE_ERROR_AT_LINE = 0 || test $REPLACE_ERROR_AT_LINE = 1; then
- COMPILE_ERROR_C=1
- else
- COMPILE_ERROR_C=0
- fi
+ m4_ifdef([gl_HAVE_MODULE_VERROR],
+ [COMPILE_ERROR_C=1],
+ [if test $HAVE_ERROR = 0 || test $REPLACE_ERROR = 1 \
+ || test $HAVE_ERROR_AT_LINE = 0 \
+ || test $REPLACE_ERROR_AT_LINE = 1; then
+ COMPILE_ERROR_C=1
+ else
+ COMPILE_ERROR_C=0
+ fi])
AC_SUBST([HAVE_ERROR])
AC_SUBST([HAVE_ERROR_AT_LINE])
verror and verror_at_line functions: Error reporting with va_list.
Files:
-lib/verror.h
-lib/verror.c
Depends-on:
-stdio
error
-xvasprintf
+
+configure.ac-early:
+AC_DEFUN([gl_HAVE_MODULE_VERROR])
configure.ac:
m4_ifdef([AM_XGETTEXT_OPTION],
AM_][XGETTEXT_OPTION([--flag=verror_at_line:5:c-format])])
Makefile.am:
-lib_SOURCES += verror.h verror.c
Include:
-"verror.h"
+<error.h>
License:
GPL
#include <config.h>
-#include "verror.h"
+#include <error.h>
#include <errno.h>
#include <stdarg.h>