bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

error: Work around an Android problem


From: Bruno Haible
Subject: error: Work around an Android problem
Date: Thu, 12 Jan 2023 16:59:30 +0100

On Android 11, the new test of the 'error' module fails:

$ cat test-error.sh.log 
--- -   2023-01-12 11:30:19.594054663 +0100
+++ err2        2023-01-12 11:30:19.567829045 +0100
@@ -6,8 +6,8 @@
 test-error:d1/foo.c:10: unsupported glink
 test-error:d1/foo.c:13: invalid brump
 test-error:d2/foo.c:13: unsupported flinge
-hammer
-boing 123 is too large
+ hammer
+ boing 123 is too large
 d2/bar.c:11: bark too loud
 test-error: can't steal: Permission denied
 test-error: fatal error
FAIL test-error.sh (exit status: 1)

The error() function adds an extra space when error_print_progname is set.

This patch works around it.


2023-01-12  Bruno Haible  <bruno@clisp.org>

        error: Work around an Android problem.
        * lib/error.in.h: Renamed from lib/error.h.
        (_GL_ATTRIBUTE_SPEC_PRINTF_ERROR): New macro.
        (error): Consider HAVE_ERROR and REPLACE_ERROR.
        (error_at_line): Consider HAVE_ERROR_AT_LINE and REPLACE_ERROR_AT_LINE.
        * m4/error_h.m4: New file, partially based on m4/error.m4.
        * m4/error.m4 (gl_ERROR): Remove the test for error_at_line.
        * modules/error-h: New file.
        * modules/error (Files): Remove lib/error.h.
        (Depends-on): Add error-h. Update conditions.
        (configure.ac): Require gl_ERROR_H. Update condition.
        * doc/glibc-headers/error.texi: Mention the 'error-h' module.
        * doc/glibc-functions/error.texi: Mention the Android problem.
        * config/srclist.txt: Add comment regarding error.h.

diff --git a/config/srclist.txt b/config/srclist.txt
index bff6a02d8e..1ff4e6ec8d 100644
--- a/config/srclist.txt
+++ b/config/srclist.txt
@@ -125,7 +125,7 @@ $LIBCSRC time/mktime-internal.h             lib
 # https://sourceware.org/bugzilla/show_bug.cgi?id=321
 #$LIBCSRC malloc/obstack.h             lib gpl
 #$LIBCSRC misc/error.c                 lib gpl
-#$LIBCSRC misc/error.h                 lib gpl
+#$LIBCSRC misc/error.h                 lib gpl (error.in.h in gnulib)
 #$LIBCSRC misc/getpass.c               lib gpl
 #$LIBCSRC misc/mkstemp.c               lib gpl
 #$LIBCSRC posix/fnmatch.c              lib gpl
diff --git a/doc/glibc-functions/error.texi b/doc/glibc-functions/error.texi
index e0977925b6..c7d63ac42b 100644
--- a/doc/glibc-functions/error.texi
+++ b/doc/glibc-functions/error.texi
@@ -24,6 +24,10 @@ Portability problems fixed by Gnulib:
 @item
 This function is missing on many non-glibc platforms:
 macOS 11.1, FreeBSD 13.0, NetBSD 9.0, OpenBSD 6.7, Minix 3.1.8, AIX 5.1, HP-UX 
11, IRIX 6.5, Solaris 11.4, Cygwin 1.7.9, mingw, MSVC 14, Android 5.1.
+@item
+This function outputs an extra space if @code{error_print_progname} is set,
+on some platforms:
+Android 11.
 @end itemize
 
 Portability problems not fixed by Gnulib:
diff --git a/doc/glibc-headers/error.texi b/doc/glibc-headers/error.texi
index 96a9a14664..4e0ccbffaa 100644
--- a/doc/glibc-headers/error.texi
+++ b/doc/glibc-headers/error.texi
@@ -18,7 +18,7 @@ Documentation:
 @uref{https://www.kernel.org/doc/man-pages/online/pages/man3/error.3.html,,man 
error}.
 @end itemize
 
-Gnulib module: error
+Gnulib module: error-h
 
 Portability problems fixed by Gnulib:
 @itemize
diff --git a/lib/error.h b/lib/error.h
deleted file mode 100644
index a240526a58..0000000000
--- a/lib/error.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* Declaration for error-reporting function
-   Copyright (C) 1995-1997, 2003, 2006, 2008-2023 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.
-
-   This file 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.
-
-   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/>.  */
-
-#ifndef _ERROR_H
-#define _ERROR_H 1
-
-/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM.  
*/
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Print a message with 'fprintf (stderr, FORMAT, ...)';
-   if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
-   If STATUS is nonzero, terminate the program with 'exit (STATUS)'.  */
-
-extern void error (int __status, int __errnum, const char *__format, ...)
-#if GNULIB_VFPRINTF_POSIX
-     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 3, 4))
-#else
-     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM, 3, 4))
-#endif
-     ;
-
-extern void error_at_line (int __status, int __errnum, const char *__fname,
-                           unsigned int __lineno, const char *__format, ...)
-#if GNULIB_VFPRINTF_POSIX
-     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, 5, 6))
-#else
-     _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM, 5, 6))
-#endif
-     ;
-
-/* 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.  */
-extern void (*error_print_progname) (void);
-
-/* This variable is incremented each time 'error' is called.  */
-extern unsigned int error_message_count;
-
-/* Sometimes we want to have at most one error per line.  This
-   variable controls whether this mode is selected or not.  */
-extern int error_one_per_line;
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* error.h */
diff --git a/lib/error.in.h b/lib/error.in.h
new file mode 100644
index 0000000000..2ac99c2817
--- /dev/null
+++ b/lib/error.in.h
@@ -0,0 +1,104 @@
+/* Declarations for error-reporting functions.
+   Copyright (C) 1995-1997, 2003, 2006, 2008-2023 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.
+
+   This file 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.
+
+   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/>.  */
+
+#ifndef _ERROR_H
+#define _ERROR_H 1
+
+/* Get _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD, _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM.  
*/
+#include <stdio.h>
+
+/* The definitions of _GL_FUNCDECL_RPL etc. are copied here.  */
+
+#if GNULIB_VFPRINTF_POSIX
+# define _GL_ATTRIBUTE_SPEC_PRINTF_ERROR _GL_ATTRIBUTE_SPEC_PRINTF_STANDARD
+#else
+# define _GL_ATTRIBUTE_SPEC_PRINTF_ERROR _GL_ATTRIBUTE_SPEC_PRINTF_SYSTEM
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Print a message with 'fprintf (stderr, FORMAT, ...)';
+   if ERRNUM is nonzero, follow it with ": " and strerror (ERRNUM).
+   If STATUS is nonzero, terminate the program with 'exit (STATUS)'.  */
+#if @REPLACE_ERROR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef error
+#  define error rpl_error
+# endif
+_GL_FUNCDECL_RPL (error, void,
+                  (int __status, int __errnum, const char *__format, ...)
+                  _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 3, 
4)));
+_GL_CXXALIAS_RPL (error, void,
+                  (int __status, int __errnum, const char *__format, ...));
+#else
+# if ! @HAVE_ERROR@
+_GL_FUNCDECL_SYS (error, void,
+                  (int __status, int __errnum, const char *__format, ...)
+                  _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 3, 
4)));
+# endif
+_GL_CXXALIAS_SYS (error, void,
+                  (int __status, int __errnum, const char *__format, ...));
+#endif
+_GL_CXXALIASWARN (error);
+
+/* Likewise.  If FILENAME is non-NULL, include FILENAME:LINENO: in the
+   message.  */
+#if @REPLACE_ERROR_AT_LINE@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+#  undef error_at_line
+#  define error_at_line rpl_error_at_line
+# endif
+_GL_FUNCDECL_RPL (error_at_line, void,
+                  (int __status, int __errnum, const char *__filename,
+                   unsigned int __lineno, const char *__format, ...)
+                  _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 5, 
6)));
+_GL_CXXALIAS_RPL (error_at_line, void,
+                  (int __status, int __errnum, const char *__filename,
+                   unsigned int __lineno, const char *__format, ...));
+#else
+# if ! @HAVE_ERROR_AT_LINE@
+_GL_FUNCDECL_SYS (error_at_line, void,
+                  (int __status, int __errnum, const char *__filename,
+                   unsigned int __lineno, const char *__format, ...)
+                  _GL_ATTRIBUTE_FORMAT ((_GL_ATTRIBUTE_SPEC_PRINTF_ERROR, 5, 
6)));
+# endif
+_GL_CXXALIAS_SYS (error_at_line, void,
+                  (int __status, int __errnum, const char *__filename,
+                   unsigned int __lineno, const char *__format, ...));
+#endif
+_GL_CXXALIASWARN (error_at_line);
+
+/* 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.  */
+extern void (*error_print_progname) (void);
+
+/* This variable is incremented each time 'error' is called.  */
+extern unsigned int error_message_count;
+
+/* Sometimes we want to have at most one error per line.  This
+   variable controls whether this mode is selected or not.  */
+extern int error_one_per_line;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* error.h */
diff --git a/m4/error.m4 b/m4/error.m4
index 8cc75dffdf..93a7558b5f 100644
--- a/m4/error.m4
+++ b/m4/error.m4
@@ -1,4 +1,4 @@
-#serial 15
+#serial 16
 
 # Copyright (C) 1996-1998, 2001-2004, 2009-2023 Free Software Foundation, Inc.
 #
@@ -8,15 +8,6 @@
 
 AC_DEFUN([gl_ERROR],
 [
-  dnl We don't use AC_FUNC_ERROR_AT_LINE any more, because it is no longer
-  dnl maintained in Autoconf and because it invokes AC_LIBOBJ.
-  AC_CACHE_CHECK([for error_at_line], [ac_cv_lib_error_at_line],
-    [AC_LINK_IFELSE(
-       [AC_LANG_PROGRAM(
-          [[#include <error.h>]],
-          [[error_at_line (0, 0, "", 0, "an error occurred");]])],
-       [ac_cv_lib_error_at_line=yes],
-       [ac_cv_lib_error_at_line=no])])
 ])
 
 # Prerequisites of lib/error.c.
diff --git a/m4/error_h.m4 b/m4/error_h.m4
new file mode 100644
index 0000000000..bb8f68ff81
--- /dev/null
+++ b/m4/error_h.m4
@@ -0,0 +1,113 @@
+# error_h.m4 serial 1
+dnl Copyright (C) 1996-2023 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl From Bruno Haible.
+dnl Provide a working "error.h".
+
+AC_DEFUN_ONCE([gl_ERROR_H],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+  gl_CHECK_FUNCS_ANDROID([error], [[#include <error.h>]])
+  if test $ac_cv_func_error = yes; then
+    HAVE_ERROR=1
+  else
+    HAVE_ERROR=0
+  fi
+  REPLACE_ERROR=0
+
+  dnl We don't use AC_FUNC_ERROR_AT_LINE any more, because it is no longer
+  dnl maintained in Autoconf and because it invokes AC_LIBOBJ.
+  dnl We need to notice a missing declaration, like gl_CHECK_FUNCS_ANDROID 
does.
+  AC_CHECK_DECL([error_at_line], , , [[#include <error.h>]])
+  if test $ac_cv_have_decl_error_at_line = yes; then
+    AC_CACHE_CHECK([for error_at_line], [ac_cv_lib_error_at_line],
+      [AC_LINK_IFELSE(
+         [AC_LANG_PROGRAM(
+            [[#include <error.h>]],
+            [[error_at_line (0, 0, "", 0, "an error occurred");]])],
+         [ac_cv_lib_error_at_line=yes],
+         [ac_cv_lib_error_at_line=no])])
+  else
+    ac_cv_lib_error_at_line=no
+  fi
+  if test $ac_cv_lib_error_at_line = yes; then
+    HAVE_ERROR_AT_LINE=1
+  else
+    HAVE_ERROR_AT_LINE=0
+  fi
+  REPLACE_ERROR_AT_LINE=0
+
+  if test $ac_cv_func_error = yes && test $ac_cv_lib_error_at_line = yes; then
+    dnl On Android 11, when error_print_progname is set, the output of the
+    dnl error() function contains an extra space.
+    AC_CACHE_CHECK([for working error function],
+      [gl_cv_func_working_error],
+      [if test $cross_compiling != yes; then
+         AC_LINK_IFELSE(
+           [AC_LANG_PROGRAM([[
+              #include <error.h>
+              static void print_no_progname (void) {}
+            ]], [[
+              error_print_progname = print_no_progname;
+              error (0, 0, "foo");
+            ]])
+           ],
+           [rm -f conftest.out
+            if test -s conftest$ac_exeext \
+               && ./conftest$ac_exeext 2> conftest.out; then
+              if grep ' ' conftest.out >/dev/null; then
+                gl_cv_func_working_error=no
+              else
+                gl_cv_func_working_error=yes
+              fi
+            else
+              gl_cv_func_working_error=no
+            fi
+            rm -f conftest.out
+           ],
+           [gl_cv_func_working_error=no])
+       else
+         AC_COMPILE_IFELSE(
+           [AC_LANG_PROGRAM([[
+              #include <error.h>
+            ]], [[
+              error (0, 0, "foo");
+            ]])
+           ],
+           [case "$host_os" in
+                               # Guess yes on glibc systems.
+              *-gnu* | gnu*)   gl_cv_func_working_error="guessing yes" ;;
+                               # Guess no on Android.
+              linux*-android*) gl_cv_func_working_error="guessing no" ;;
+                               # If we don't know, obey --enable-cross-guesses.
+              *)               
gl_cv_func_working_error="$gl_cross_guess_normal" ;;
+            esac
+           ],
+           [gl_cv_func_working_error=no])
+       fi
+      ])
+    case "$gl_cv_func_working_error" in
+      *no)
+        REPLACE_ERROR=1
+        REPLACE_ERROR_AT_LINE=1
+        ;;
+    esac
+  fi
+
+  if test $HAVE_ERROR = 0 || test $REPLACE_ERROR = 1 \
+     || test $HAVE_ERROR_AT_LINE = 0 || test $REPLACE_ERROR_AT_LINE = 1; then
+    dnl Provide a substitute <error.h> file.
+    GL_GENERATE_ERROR_H=true
+  else
+    GL_GENERATE_ERROR_H=false
+  fi
+
+  AC_SUBST([HAVE_ERROR])
+  AC_SUBST([HAVE_ERROR_AT_LINE])
+  AC_SUBST([REPLACE_ERROR])
+  AC_SUBST([REPLACE_ERROR_AT_LINE])
+])
diff --git a/modules/error b/modules/error
index e8363528aa..5f716865a9 100644
--- a/modules/error
+++ b/modules/error
@@ -2,20 +2,21 @@ Description:
 error and error_at_line functions: Error reporting.
 
 Files:
-lib/error.h
 lib/error.c
 m4/error.m4
 
 Depends-on:
+error-h
 stdio
 getprogname
-strerror        [test $ac_cv_lib_error_at_line = no]
-unistd          [test $ac_cv_lib_error_at_line = no]
-msvc-nothrow    [test $ac_cv_lib_error_at_line = no]
+strerror        [test $GL_GENERATE_ERROR_H = true]
+unistd          [test $GL_GENERATE_ERROR_H = true]
+msvc-nothrow    [test $GL_GENERATE_ERROR_H = true]
 
 configure.ac:
+AC_REQUIRE([gl_ERROR_H])
 gl_ERROR
-gl_CONDITIONAL([GL_COND_OBJ_ERROR], [test "$ac_cv_lib_error_at_line" = no])
+gl_CONDITIONAL([GL_COND_OBJ_ERROR], [test $GL_GENERATE_ERROR_H = true])
 AM_COND_IF([GL_COND_OBJ_ERROR], [
   gl_PREREQ_ERROR
 ])
diff --git a/modules/error-h b/modules/error-h
new file mode 100644
index 0000000000..80bc06194b
--- /dev/null
+++ b/modules/error-h
@@ -0,0 +1,46 @@
+Description:
+Functions for error reporting.
+
+Files:
+lib/error.in.h
+m4/error_h.m4
+
+Depends-on:
+gen-header
+snippet/c++defs
+
+configure.ac:
+gl_ERROR_H
+gl_CONDITIONAL_HEADER([error.h])
+AC_PROG_MKDIR_P
+
+Makefile.am:
+BUILT_SOURCES += $(ERROR_H)
+
+# We need the following in order to create <error.h> when the system
+# doesn't have one that works.
+if GL_GENERATE_ERROR_H
+error.h: error.in.h $(top_builddir)/config.status $(CXXDEFS_H)
+@NMD@  $(AM_V_GEN)$(MKDIR_P) '%reldir%'
+       $(gl_V_at)$(SED_HEADER_STDOUT) \
+             -e 's|@''HAVE_ERROR''@|$(HAVE_ERROR)|g' \
+             -e 's|@''HAVE_ERROR_AT_LINE''@|$(HAVE_ERROR_AT_LINE)|g' \
+             -e 's|@''REPLACE_ERROR''@|$(REPLACE_ERROR)|g' \
+             -e 's|@''REPLACE_ERROR_AT_LINE''@|$(REPLACE_ERROR_AT_LINE)|g' \
+             -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \
+             $(srcdir)/error.in.h > $@-t
+       $(AM_V_at)mv $@-t $@
+else
+error.h: $(top_builddir)/config.status
+       rm -f $@
+endif
+MOSTLYCLEANFILES += error.h error.h-t
+
+Include:
+"error.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all






reply via email to

[Prev in Thread] Current Thread [Next in Thread]