Readline Maintainers,

Summary:
I think I found a (minor) bug in readline 8.2; details follow, and "config.h" 
is attached. Things build fine, and I can use the library, but some of the 
header files that are installed with "make && make install" have some issues in 
them which I will describe in more detail below. One of the issues I describe 
below appears to be a genuine bug you probably care about. The problems 
manifests by including the readline library header file "readline.h" and using 
"-Werror -Wstrict-prototypes" with GCC when building a user program, which 
causes the build to fail.

I found the following readline page:
https://tiswww.case.edu/php/chet/readline/rltop.html

I downloaded readline from the following link:
http://git.savannah.gnu.org/cgit/readline.git/snapshot/readline-master.tar.gz

I then extracted the tarball (readline 8.2) and ran the following commands to 
build the library:

export 
CC=/dept/Boston/avose/riscv/tools/install/riscv-gnu/bin/riscv64-unknown-linux-gnu-gcc
./configure --prefix /dept/Boston/avose/riscv/tools/install/riscv-readline 
--disable-shared --host=riscv64-unknown-linux-gnu --with-curses

I know the above is a cross-compile to RISCV, but I don't think this problem is 
specific to the ISA, as I've seen the exact same issues with ARM installs of 
readline 8.2 as well. The issue comes from two places in the header files. One 
(1) is, I think, an actual issue you want to know about and probably want to 
fix, the other (2) is probably a more minor thing, but you might still want to 
know about it, and may want to think about a fix for it.

(1)
This first issue may actually be a problem you care about. What happens is that 
"readline.h" contains the following code, which in and of itself isn't the 
issue, this is just where the compiler warning / error initially comes from:

#if defined (USE_VARARGS) && defined (PREFER_STDARG)
extern int rl_message (const char *, ...)  __attribute__((__format__ (printf, 
1, 2)));
#else
extern int rl_message ();
#endif

The configure process did find "stdarg.h" as can be seen in the attached 
"config.h" file:

/* Define if you have the <stdarg.h> header file.  */
#define HAVE_STDARG_H 1

However, the "readline.h" file in the install location uses the second 
prototype: "extern int rl_message ();". It should instead be using the first 
one: "extern int rl_message (const char *, ...)  __attribute__((__format__ 
(printf, 1, 2)));". This is caused by an issue in a file included by 
"readline.h" called "rlstdc.h". The problematic code in "rlstdc.h" follows:

#if defined (__STDC__) && defined (HAVE_STDARG_H)
#  define PREFER_STDARG
#  define USE_VARARGS
#else
#  if defined (HAVE_VARARGS_H)
#    define PREFER_VARARGS
#    define USE_VARARGS
#  endif
#endif

During the build process, this is fine because "HAVE_STDARG_H" is defined. This 
then causes "PREFER_STDARG" and "USE_VARARGS" to be defined. So, in the build 
process, the correct prototype for "rl_message" is used: "extern int rl_message 
(const char *, ...)  __attribute__((__format__ (printf, 1, 2)));". However, 
when user programs include "readline.h" and try to build, "HAVE_STDARG_H" is 
not defined, and the wrong prototype for "message" is used: "extern int 
rl_message ();". This is because the check for "HAVE_STDARG_H" has been 
"leaked" out of the build environment into the standard installed readline 
header files. I don't think the installed header files should have a check for 
"HAVE_STDARG_H" in them. This seems like an actual bug, and it should probably 
be fixed.

My solution here was a hack. I did the following to resolve the error:

//!!avose: HAVE_STDARG_H was defined during configure, but this macro is not
//!!avose: included anywhere in the include files for users of readline.
//!!avose: Thus, this edit includes it below. This is needed to avoid issues
//!!avose: from "-Werror=strict-prototypes"
#ifndef HAVE_STDARG_H
#define HAVE_STDARG_H
#define AVOSE_FIX_HAVE_STDARG_H
#endif
#if defined (__STDC__) && defined (HAVE_STDARG_H)
#  define PREFER_STDARG
#  define USE_VARARGS
#else
#  if defined (HAVE_VARARGS_H)
#    define PREFER_VARARGS
#    define USE_VARARGS
#  endif
#endif
#ifdef AVOSE_FIX_HAVE_STDARG_H
#undef HAVE_STDARG_H
#undef AVOSE_FIX_HAVE_STDARG_H
#endif

(2)
This second issue is something you may not care about as much. The second issue 
is another place where compiling a user program that includes "readline.h" is 
an issue combined with "-Werror -Wstrict-prototypes". In this second issue, the 
problem is in the header file "rltypedefs.h". The section containing the issue 
is as follows:

#if defined(__GNUC__) || defined(__clang__)
typedef int Function () __attribute__((deprecated));
typedef void VFunction () __attribute__((deprecated));
typedef char *CPFunction () __attribute__((deprecated));
typedef char **CPPFunction () __attribute__((deprecated));
#else
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction ();
typedef char **CPPFunction ();
#endif

These prototypes don't actually appear to be used anywhere by user programs 
compiling and linking with readline, and they are an error with "-Werror 
-Wstrict-prototypes". My solution here was to just disable this whole block of 
code with "#if 0" as shown below. You may not care too much about this, I 
suppose, just mentioning it.

//!!avose: The following types aren't needed anywhere I can see
//!!avose: and they cause warnings from -Werror=strict-prototypes
#if 0
#if defined(__GNUC__) || defined(__clang__)
typedef int Function () __attribute__((deprecated));
typedef void VFunction () __attribute__((deprecated));
typedef char *CPFunction () __attribute__((deprecated));
typedef char **CPPFunction () __attribute__((deprecated));
#else
typedef int Function ();
typedef void VFunction ();
typedef char *CPFunction ();
typedef char **CPPFunction ();
#endif
#endif

It would be wonderful if someone could take a look at these issues, and 
possible fix them upstream so that others might avoid the problems that I've 
been hitting here. Thanks so much for your time.

Thanks much,
~Aaron Vose

/* config.h.  Generated from config.h.in by configure.  */
/* config.h.in.  Maintained by hand. */

/* Template definitions for autoconf */

/* These are set by AC_USE_SYSTEM_EXTENSIONS */
#define __EXTENSIONS__ 1
#define _ALL_SOURCE 1
#define _GNU_SOURCE 1
/* #undef _POSIX_SOURCE */
/* #undef _POSIX_1_SOURCE */
#define _POSIX_PTHREAD_SEMANTICS 1
#define _TANDEM_SOURCE 1
/* #undef _MINIX */

/* Define NO_MULTIBYTE_SUPPORT to not compile in support for multibyte
   characters, even if the OS supports them. */
/* #undef NO_MULTIBYTE_SUPPORT */

/* #undef _FILE_OFFSET_BITS */

/* Characteristics of the compiler. */
/* #undef inline */

/* #undef sig_atomic_t */

/* #undef size_t */

/* #undef ssize_t */

/* #undef const */

/* #undef volatile */

#define PROTOTYPES 1
#define __PROTOTYPES 1

#define __CHAR_UNSIGNED__ 1

/* Define if the `S_IS*' macros in <sys/stat.h> do not work properly.  */
/* #undef STAT_MACROS_BROKEN */

/* Define if you have the chown function. */
#define HAVE_CHOWN 1

/* Define if you have the fcntl function. */
#define HAVE_FCNTL 1

/* Define if you have the fnmatch function. */
#define HAVE_FNMATCH 1

/* Define if you have the getpwent function. */
#define HAVE_GETPWENT 1

/* Define if you have the getpwnam function. */
#define HAVE_GETPWNAM 1

/* Define if you have the getpwuid function. */
#define HAVE_GETPWUID 1

/* Define if you have the gettimeofday function. */
#define HAVE_GETTIMEOFDAY 1

/* Define if you have the isascii function. */
#define HAVE_ISASCII 1

/* Define if you have the iswctype function.  */
#define HAVE_ISWCTYPE 1

/* Define if you have the iswlower function.  */
#define HAVE_ISWLOWER 1

/* Define if you have the iswupper function.  */
#define HAVE_ISWUPPER 1

/* Define if you have the isxdigit function. */
#define HAVE_ISXDIGIT 1

/* Define if you have the kill function. */
#define HAVE_KILL 1

/* Define if you have the lstat function. */
#define HAVE_LSTAT 1

/* Define if you have the mbrlen function. */
#define HAVE_MBRLEN 1

/* Define if you have the mbrtowc function. */
#define HAVE_MBRTOWC 1

/* Define if you have the mbsrtowcs function. */
#define HAVE_MBSRTOWCS 1

/* Define if you have the memmove function. */
#define HAVE_MEMMOVE 1

/* Define if you have the pselect function.  */
#define HAVE_PSELECT 1

/* Define if you have the putenv function.  */
#define HAVE_PUTENV 1

/* Define if you have the readlink function.  */
#define HAVE_READLINK 1

/* Define if you have the select function.  */
#define HAVE_SELECT 1

/* Define if you have the setenv function.  */
#define HAVE_SETENV 1

/* Define if you have the setitimer function.  */
#define HAVE_SETITIMER 1

/* Define if you have the setlocale function. */
#define HAVE_SETLOCALE 1

/* Define if you have the strcasecmp function.  */
#define HAVE_STRCASECMP 1

/* Define if you have the strcoll function.  */
#define HAVE_STRCOLL 1

/* #undef STRCOLL_BROKEN */

/* Define if you have the strpbrk function.  */
#define HAVE_STRPBRK 1

/* Define if you have the sysconf function.  */
#define HAVE_SYSCONF 1

/* Define if you have the tcgetattr function.  */
#define HAVE_TCGETATTR 1

/* Define if you have the towlower function.  */
#define HAVE_TOWLOWER 1

/* Define if you have the towupper function.  */
#define HAVE_TOWUPPER 1

/* Define if you have the vsnprintf function.  */
#define HAVE_VSNPRINTF 1

/* Define if you have the wcrtomb function.  */
#define HAVE_WCRTOMB 1

/* Define if you have the wcscoll function.  */
#define HAVE_WCSCOLL 1

/* Define if you have the wctype function.  */
#define HAVE_WCTYPE 1

/* Define if you have the wcwidth function.  */
#define HAVE_WCWIDTH 1

/* and whether it works */
/* #undef WCWIDTH_BROKEN */

/* Define if you have the <dirent.h> header file.  */
#define HAVE_DIRENT_H 1

/* Define if you have the <fcntl.h> header file.  */
#define HAVE_FCNTL_H 1

/* Define if you have the <langinfo.h> header file.  */
#define HAVE_LANGINFO_H 1

/* Define if you have the <libaudit.h> header file.  */
/* #undef HAVE_LIBAUDIT_H */

/* Define if you have the <limits.h> header file.  */
#define HAVE_LIMITS_H 1

/* Define if you have the <locale.h> header file.  */
#define HAVE_LOCALE_H 1

/* Define if you have the <memory.h> header file.  */
#define HAVE_MEMORY_H 1

/* Define if you have the <ndir.h> header file.  */
/* #undef HAVE_NDIR_H */

/* Define if you have the <ncurses/termcap.h> header file.  */
/* #undef HAVE_NCURSES_TERMCAP_H */

/* Define if you have the <pwd.h> header file.  */
#define HAVE_PWD_H 1

/* Define if you have the <stdarg.h> header file.  */
#define HAVE_STDARG_H 1

/* Define if you have the <stdbool.h> header file.  */
#define HAVE_STDBOOL_H 1

/* Define if you have the <stdlib.h> header file.  */
#define HAVE_STDLIB_H 1

/* Define if you have the <string.h> header file.  */
#define HAVE_STRING_H 1

/* Define if you have the <strings.h> header file.  */
#define HAVE_STRINGS_H 1

/* Define if you have the <sys/dir.h> header file.  */
/* #undef HAVE_SYS_DIR_H */

/* Define if you have the <sys/file.h> header file.  */
#define HAVE_SYS_FILE_H 1

/* Define if you have the <sys/ioctl.h> header file.  */
#define HAVE_SYS_IOCTL_H 1

/* Define if you have the <sys/ndir.h> header file.  */
/* #undef HAVE_SYS_NDIR_H */

/* Define if you have the <sys/pte.h> header file.  */
/* #undef HAVE_SYS_PTE_H */

/* Define if you have the <sys/ptem.h> header file.  */
/* #undef HAVE_SYS_PTEM_H */

/* Define if you have the <sys/select.h> header file.  */
#define HAVE_SYS_SELECT_H 1

/* Define if you have the <sys/stream.h> header file.  */
/* #undef HAVE_SYS_STREAM_H */

/* Define if you have the <sys/time.h> header file.  */
#define HAVE_SYS_TIME_H 1

/* Define if you have the <termcap.h> header file.  */
/* #undef HAVE_TERMCAP_H */

/* Define if you have the <termio.h> header file.  */
#define HAVE_TERMIO_H 1

/* Define if you have the <termios.h> header file.  */
#define HAVE_TERMIOS_H 1

/* Define if you have the <unistd.h> header file.  */
#define HAVE_UNISTD_H 1

/* Define if you have the <varargs.h> header file.  */
/* #undef HAVE_VARARGS_H */

/* Define if you have the <wchar.h> header file.  */
#define HAVE_WCHAR_H 1

/* Define if you have the <wctype.h> header file.  */
#define HAVE_WCTYPE_H 1

#define HAVE_MBSTATE_T 1

/* Define if you have wchar_t in <wctype.h>. */
#define HAVE_WCHAR_T 1

/* Define if you have wctype_t in <wctype.h>. */
#define HAVE_WCTYPE_T 1

/* Define if you have wint_t in <wctype.h>. */  
#define HAVE_WINT_T 1

/* Define if you have <langinfo.h> and nl_langinfo(CODESET). */
#define HAVE_LANGINFO_CODESET 1

/* Define if you have <linux/audit.h> and it defines AUDIT_USER_TTY */
#define HAVE_DECL_AUDIT_USER_TTY 1

/* Definitions pulled in from aclocal.m4. */
#define GWINSZ_IN_SYS_IOCTL 1

#define STRUCT_WINSIZE_IN_SYS_IOCTL 1

/* #undef STRUCT_WINSIZE_IN_TERMIOS */

/* #undef TIOCSTAT_IN_SYS_IOCTL */

#define FIONREAD_IN_SYS_IOCTL 1

/* #undef SPEED_T_IN_SYS_TYPES */

#define HAVE_GETPW_DECLS 1

#define HAVE_STRUCT_DIRENT_D_INO 1

#define HAVE_STRUCT_DIRENT_D_FILENO 1

/* #undef HAVE_STRUCT_DIRENT_D_NAMLEN */

#define HAVE_TIMEVAL 1

/* #undef HAVE_BSD_SIGNALS */

#define HAVE_POSIX_SIGNALS 1

/* #undef HAVE_USG_SIGHOLD */

/* #undef MUST_REINSTALL_SIGHANDLERS */

#define HAVE_POSIX_SIGSETJMP 1

/* #undef CTYPE_NON_ASCII */

/* modify settings or make new ones based on what autoconf tells us. */

/* Ultrix botches type-ahead when switching from canonical to
   non-canonical mode, at least through version 4.3 */
#if !defined (HAVE_TERMIOS_H) || !defined (HAVE_TCGETATTR) || defined (ultrix)
#  define TERMIOS_MISSING
#endif

/* VARARGS defines moved to rlstdc.h */

Reply via email to