about summary refs log tree commit diff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/features.h22
-rw-r--r--include/stdio.h11
2 files changed, 32 insertions, 1 deletions
diff --git a/include/features.h b/include/features.h
index dc9f8fa9ac..c9bc534e27 100644
--- a/include/features.h
+++ b/include/features.h
@@ -140,6 +140,7 @@
 #undef	__USE_FORTIFY_LEVEL
 #undef	__KERNEL_STRICT_NAMES
 #undef	__GLIBC_USE_DEPRECATED_GETS
+#undef	__GLIBC_USE_DEPRECATED_SCANF
 
 /* Suppress kernel-name space pollution unless user expressedly asks
    for it.  */
@@ -401,6 +402,27 @@
 # define __GLIBC_USE_DEPRECATED_GETS 1
 #endif
 
+/* GNU formerly extended the scanf functions with modified format
+   specifiers %as, %aS, and %a[...] that allocate a buffer for the
+   input using malloc.  This extension conflicts with ISO C99, which
+   defines %a as a standalone format specifier that reads a floating-
+   point number; moreover, POSIX.1-2008 provides the same feature
+   using the modifier letter 'm' instead (%ms, %mS, %m[...]).
+
+   We now follow C99 unless GNU extensions are active and the compiler
+   is specifically in C89 or C++98 mode (strict or not).  For
+   instance, with GCC, -std=gnu11 will have C99-compliant scanf with
+   or without -D_GNU_SOURCE, but -std=c89 -D_GNU_SOURCE will have the
+   old extension.  */
+#if defined __USE_GNU &&						\
+  (defined __cplusplus							\
+   ? (__cplusplus < 201103L && !defined __GXX_EXPERIMENTAL_CXX0X__)	\
+   : (!defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L))
+# define __GLIBC_USE_DEPRECATED_SCANF 1
+#else
+# define __GLIBC_USE_DEPRECATED_SCANF 0
+#endif
+
 /* Get definitions of __STDC_* predefined macros, if the compiler has
    not preincluded this header automatically.  */
 #include <stdc-predef.h>
diff --git a/include/stdio.h b/include/stdio.h
index 1b7da0f74d..65ccabbb05 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -64,9 +64,19 @@ extern int __isoc99_vscanf (const char *__restrict __format,
 extern int __isoc99_vsscanf (const char *__restrict __s,
 			     const char *__restrict __format,
 			     __gnuc_va_list __arg) __THROW;
+libc_hidden_proto (__isoc99_sscanf)
 libc_hidden_proto (__isoc99_vsscanf)
 libc_hidden_proto (__isoc99_vfscanf)
 
+/* Internal uses of sscanf should call the C99-compliant version.
+   Unfortunately, symbol redirection is not transitive, so the
+   __REDIRECT in the public header does not link up with the above
+   libc_hidden_proto.  Bridge the gap with a macro.  */
+#  if !__GLIBC_USE (DEPRECATED_SCANF)
+#   undef sscanf
+#   define sscanf __isoc99_sscanf
+#  endif
+
 /* Prototypes for compatibility functions.  */
 extern FILE *__new_tmpfile (void);
 extern FILE *__old_tmpfile (void);
@@ -171,7 +181,6 @@ libc_hidden_proto (__dprintf)
 libc_hidden_proto (fprintf)
 libc_hidden_proto (vfprintf)
 libc_hidden_proto (sprintf)
-libc_hidden_proto (sscanf)
 libc_hidden_proto (fwrite)
 libc_hidden_proto (perror)
 libc_hidden_proto (remove)