mirror of
https://sourceware.org/git/glibc.git
synced 2025-05-20 16:33:46 +03:00
The getc and putc macros in the public stdio.h expand to call _IO_getc and _IO_putc respectively. As _IO_getc, fgetc, and getc are all aliases for the same function, and _IO_putc, fputc, and putc are also all aliases for the same function, the macros are pointless. The C standard does not require getc and putc to be macros, so let's just not have macros. All four symbols are exported from libc.so at the same, ancient symbol version, so there should be no risks for binary compatibility. Similarly, the getchar and putchar inlines in bits/stdio.h forward to getc and putc instead of their _IO_ aliases. As a change from longstanding historical practice, this does seem like it might break _something_, so there is a note in NEWS, which is also a convenient place to advise people that if they thought getc and putc had reduced per-character overhead they should consider using getc_unlocked and putc_unlocked instead. (These are also not macros, but when optimizing, they are inlines.) * libio/stdio.h: Don't define getc or putc as macros. * libio/bits/stdio.h (getchar, putchar): Use getc and putc, not _IO_getc and _IO_putc.
191 lines
5.4 KiB
C
191 lines
5.4 KiB
C
/* Optimizing macros and inline functions for stdio functions.
|
|
Copyright (C) 1998-2018 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
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.
|
|
|
|
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.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with the GNU C Library; if not, see
|
|
<http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef _STDIO_H
|
|
# error "Never include <bits/stdio.h> directly; use <stdio.h> instead."
|
|
#endif
|
|
|
|
#ifndef __extern_inline
|
|
# define __STDIO_INLINE inline
|
|
#else
|
|
# define __STDIO_INLINE __extern_inline
|
|
#endif
|
|
|
|
|
|
#ifdef __USE_EXTERN_INLINES
|
|
/* For -D_FORTIFY_SOURCE{,=2} bits/stdio2.h will define a different
|
|
inline. */
|
|
# if !(__USE_FORTIFY_LEVEL > 0 && defined __fortify_function)
|
|
/* Write formatted output to stdout from argument list ARG. */
|
|
__STDIO_INLINE int
|
|
vprintf (const char *__restrict __fmt, _G_va_list __arg)
|
|
{
|
|
return vfprintf (stdout, __fmt, __arg);
|
|
}
|
|
# endif
|
|
|
|
/* Read a character from stdin. */
|
|
__STDIO_INLINE int
|
|
getchar (void)
|
|
{
|
|
return getc (stdin);
|
|
}
|
|
|
|
|
|
# ifdef __USE_MISC
|
|
/* Faster version when locking is not necessary. */
|
|
__STDIO_INLINE int
|
|
fgetc_unlocked (FILE *__fp)
|
|
{
|
|
return _IO_getc_unlocked (__fp);
|
|
}
|
|
# endif /* misc */
|
|
|
|
|
|
# ifdef __USE_POSIX
|
|
/* This is defined in POSIX.1:1996. */
|
|
__STDIO_INLINE int
|
|
getc_unlocked (FILE *__fp)
|
|
{
|
|
return _IO_getc_unlocked (__fp);
|
|
}
|
|
|
|
/* This is defined in POSIX.1:1996. */
|
|
__STDIO_INLINE int
|
|
getchar_unlocked (void)
|
|
{
|
|
return _IO_getc_unlocked (stdin);
|
|
}
|
|
# endif /* POSIX */
|
|
|
|
|
|
/* Write a character to stdout. */
|
|
__STDIO_INLINE int
|
|
putchar (int __c)
|
|
{
|
|
return putc (__c, stdout);
|
|
}
|
|
|
|
|
|
# ifdef __USE_MISC
|
|
/* Faster version when locking is not necessary. */
|
|
__STDIO_INLINE int
|
|
fputc_unlocked (int __c, FILE *__stream)
|
|
{
|
|
return _IO_putc_unlocked (__c, __stream);
|
|
}
|
|
# endif /* misc */
|
|
|
|
|
|
# ifdef __USE_POSIX
|
|
/* This is defined in POSIX.1:1996. */
|
|
__STDIO_INLINE int
|
|
putc_unlocked (int __c, FILE *__stream)
|
|
{
|
|
return _IO_putc_unlocked (__c, __stream);
|
|
}
|
|
|
|
/* This is defined in POSIX.1:1996. */
|
|
__STDIO_INLINE int
|
|
putchar_unlocked (int __c)
|
|
{
|
|
return _IO_putc_unlocked (__c, stdout);
|
|
}
|
|
# endif /* POSIX */
|
|
|
|
|
|
# ifdef __USE_GNU
|
|
/* Like `getdelim', but reads up to a newline. */
|
|
__STDIO_INLINE _IO_ssize_t
|
|
getline (char **__lineptr, size_t *__n, FILE *__stream)
|
|
{
|
|
return __getdelim (__lineptr, __n, '\n', __stream);
|
|
}
|
|
# endif /* GNU */
|
|
|
|
|
|
# ifdef __USE_MISC
|
|
/* Faster versions when locking is not required. */
|
|
__STDIO_INLINE int
|
|
__NTH (feof_unlocked (FILE *__stream))
|
|
{
|
|
return _IO_feof_unlocked (__stream);
|
|
}
|
|
|
|
/* Faster versions when locking is not required. */
|
|
__STDIO_INLINE int
|
|
__NTH (ferror_unlocked (FILE *__stream))
|
|
{
|
|
return _IO_ferror_unlocked (__stream);
|
|
}
|
|
# endif /* misc */
|
|
|
|
#endif /* Use extern inlines. */
|
|
|
|
|
|
#if defined __USE_MISC && defined __GNUC__ && defined __OPTIMIZE__ \
|
|
&& !defined __cplusplus
|
|
/* Perform some simple optimizations. */
|
|
# define fread_unlocked(ptr, size, n, stream) \
|
|
(__extension__ ((__builtin_constant_p (size) && __builtin_constant_p (n) \
|
|
&& (size_t) (size) * (size_t) (n) <= 8 \
|
|
&& (size_t) (size) != 0) \
|
|
? ({ char *__ptr = (char *) (ptr); \
|
|
FILE *__stream = (stream); \
|
|
size_t __cnt; \
|
|
for (__cnt = (size_t) (size) * (size_t) (n); \
|
|
__cnt > 0; --__cnt) \
|
|
{ \
|
|
int __c = _IO_getc_unlocked (__stream); \
|
|
if (__c == EOF) \
|
|
break; \
|
|
*__ptr++ = __c; \
|
|
} \
|
|
((size_t) (size) * (size_t) (n) - __cnt) \
|
|
/ (size_t) (size); }) \
|
|
: (((__builtin_constant_p (size) && (size_t) (size) == 0) \
|
|
|| (__builtin_constant_p (n) && (size_t) (n) == 0)) \
|
|
/* Evaluate all parameters once. */ \
|
|
? ((void) (ptr), (void) (stream), (void) (size), \
|
|
(void) (n), (size_t) 0) \
|
|
: fread_unlocked (ptr, size, n, stream))))
|
|
|
|
# define fwrite_unlocked(ptr, size, n, stream) \
|
|
(__extension__ ((__builtin_constant_p (size) && __builtin_constant_p (n) \
|
|
&& (size_t) (size) * (size_t) (n) <= 8 \
|
|
&& (size_t) (size) != 0) \
|
|
? ({ const char *__ptr = (const char *) (ptr); \
|
|
FILE *__stream = (stream); \
|
|
size_t __cnt; \
|
|
for (__cnt = (size_t) (size) * (size_t) (n); \
|
|
__cnt > 0; --__cnt) \
|
|
if (_IO_putc_unlocked (*__ptr++, __stream) == EOF) \
|
|
break; \
|
|
((size_t) (size) * (size_t) (n) - __cnt) \
|
|
/ (size_t) (size); }) \
|
|
: (((__builtin_constant_p (size) && (size_t) (size) == 0) \
|
|
|| (__builtin_constant_p (n) && (size_t) (n) == 0)) \
|
|
/* Evaluate all parameters once. */ \
|
|
? ((void) (ptr), (void) (stream), (void) (size), \
|
|
(void) (n), (size_t) 0) \
|
|
: fwrite_unlocked (ptr, size, n, stream))))
|
|
#endif
|
|
|
|
/* Define helper macro. */
|
|
#undef __STDIO_INLINE
|