标准I/O库.
这个东东一般只要上个C语言的人都学过.比如printf函数.这些东东,大都是建立在一个叫FILE的对象上.
下面我清数下这此函数.(可能还有很多没有!)
int fwide(FILE *fp,int mode); //流处理是宽字节还是字节的或者无字节的,看下面的_IO_fwide_maybe_incompatible
void setbuf(FILE* fp,char *restrict buf); //设置文件流是是行缓冲,还是全缓冲,一般是全缓冲,但与具体设备相关就不一定了.
int setvbuf(FILE* fp,char *restrict buf,int mode,size_t size);//同上,但是指出是什么样的缓冲
int fflush(FILE *fp); //刷新缓冲区
FILE* fopen(const char *restrict pathname,const char *restrict type); //看下篇
FILE* freopen(const char *restrict pathname,const char * restrict type,FILE *restrict fp);//相当于先关闭,再打开一次
FILE* fdopen(int filedes,const char *type);//根据文件描述符打开文件流
int getc(FILE *fp); //下面已经有实现宏
int fgetc(FILE *fp); //功能和getc一样,但是它是个函数,而getc是一个宏
int getchar(void); //他从stdin里取数据,看下面_IO_stdin宏
//以上三个函数成功都返回下一个字符
#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) //是否文件结束
#define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) //判断标志,是否出错
int ferror(FILE *fp); //判断是否出错 ,具体看下面
int feof(FILE *fp); //判断是否到文件尾
void clearerr(FILE *fp); //清除上面两个标志
ungetc(int c,FILE *fp); //倒序取流的字节
int putc(int c,FILE *fp); //_IO_putc_unlocked
int fputc(int c,FILE *fp);
int putchar(int c);
char* fgets(char *restrict buf,int n,FILE*restrict fp);//看下篇,其实是用_IO_putc_unlocked实现的
char* gets(char *buf); //这个函数和上面基本一样,取的设备是stdout,但没有缓冲区大小,可能溢出
//注意这里是结构读写,并不是字节读写.nobj对象个数,size表示一个对象的大小,ptr为缓冲指针
size_t fread(void *restrict ptr,size_t size,size_t nobj,FILE *restrict fp); //看下篇
size_t fwrite(const void* restrict ptr,size_t size,size_t nobj,FILE *restrict fp);
long ftell(FILE *fp); //返回流的当前位置,我们现在看到了FILE结构,所以这个很简单吧.
int fseek(FILE *fp,long offset,int whence); //设置流的当前位置
void rewind(FILE *fp); //直接设置流到起始位置,无返回值.
off_t ftello(FILE *fp); //可以看出这两个函数和上面的两个一样,只是long 变成了off_t,实际他功能确实如此
int fseeko(FILE *fp,off_t offset,int whence);
int fgetpos(FILE *restrict fp,fpos_t *restrict pos); //这两个函数和fseek及ftell,只是他们将位置放到了参数内部
int fsetpos(FILE *fp,const fpos_t *pos); //并且文件偏移类型也由long -->fpos_t了.
//下面八个格式化输出
int printf(const char *restrict format,...); //格式化输出到stdout里
int fprintf(FILE *fp,const char *restrict format,...); //格式化输出到fp
int sprintf(char *restrict buf, const char *restrict format,...); //格式化输出到字符数组里
int snprintf(char *restrict buf,size_t n,const char* restrict format,...); //格式化输出到指定长度的数组里
int vprintf(const char *restrict format ,va_list arg); //这四个函数和上面一模一样,只是将va_list arg代替...,
int vfprintf(FILE* restrict fp,const char *restrict format,va_list arg); //其实实际编译后台也会作此转换的.
int vsprintf(char * restrict buf,const char *restrict format,va_list arg);
int vsnprintf(char * restrict buf,size_t n,const char *restrict format,va_list arg);
//再下面六个格式化输入
int scanf(const char *restrict format,...); //从stdin里输入,不用说.记得...代表是地址.
int fscanf(FILE *restrict fp,const char *restrict format,...); //上面一样,stdin变成了fp
int sscanf(const char *restrict buf,const char *restrict format,...); //从一数组里格式化输入
int vscanf(const char *restrict format,va_list arg); //同上
int vfscanf(FILE *restrict fp,const char *restrict format,va_list arg);
int vsscanf(const char *restrict buf,const char *restrict format,va_list arg);
int fileno(FILE* fp); //看_IO_FILE就知道,int _fileno; 这是内部成员,所以一个宏就可以实现//获取文件描述符
char *tmpnam(char *ptr); //产生一个临时文件
FILE *tmpfile(void); //产生一个流的临时文件
char *tempnam(const char* directory,const char *prefix); //指定了具体的路径,和前缀,但前缀最多只能5个字符
int mkstemp(char *template);//返回一临时文件的文件描述符.它的前半部应该是先打开临时文件,并返回描述符.
//以下是他最有用的一个文件,来自于glibc-->libio.h,定义了几乎所有重要结构,看我解释
#ifndef _IO_STDIO_H
#define _IO_STDIO_H
#include //这个不管,一些全局配置,关于下面这个变量的实际定义
/* ALL of these should be defined in _G_config.h */
#define _IO_pos_t _G_fpos_t /* obsolete */
#define _IO_fpos_t _G_fpos_t
#define _IO_fpos64_t _G_fpos64_t
#define _IO_size_t _G_size_t
#define _IO_ssize_t _G_ssize_t
#define _IO_off_t _G_off_t
#define _IO_off64_t _G_off64_t
#define _IO_pid_t _G_pid_t
#define _IO_uid_t _G_uid_t
#define _IO_iconv_t _G_iconv_t
#define _IO_HAVE_SYS_WAIT _G_HAVE_SYS_WAIT
#define _IO_HAVE_ST_BLKSIZE _G_HAVE_ST_BLKSIZE
#define _IO_BUFSIZ _G_BUFSIZ
#define _IO_va_list _G_va_list
#define _IO_wint_t _G_wint_t
#ifdef _G_NEED_STDARG_H //是否要参数文件,即,它主要实现了va_list,va_start,va_arg,va_end;
/* This define avoids name pollution if we're using GNU stdarg.h */
# define __need___va_list
# include # ifdef __GNUC_VA_LIST
# undef _IO_va_list
# define _IO_va_list __gnuc_va_list
# endif /* __GNUC_VA_LIST */
#endif
#ifndef __P //这个我也不知道
# if _G_HAVE_SYS_CDEFS
# include # else
# ifdef __STDC__
# define __P(p) p
# define __PMT(p) p
# else
# define __P(p) ()
# define __PMT(p) ()
# endif
# endif
#endif /*!__P*/
/* For backward compatibility */
#ifndef _PARAMS
# define _PARAMS(protos) __P(protos)
#endif /*!_PARAMS*/
#ifndef __STDC__
# ifndef const
# define const
# endif
#endif
#define _IO_UNIFIED_JUMPTABLES 1
#ifndef _G_HAVE_PRINTF_FP
# define _IO_USE_DTOA 1
#endif
#ifndef EOF //如果没有定义EOF,则定义它为-1
# define EOF (-1)
#endif
#ifndef NULL
# if defined __GNUG__ && \
(__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8))
# define NULL (__null)
# else
# if !defined(__cplusplus) //如果不是C++,则定义为指向0的空指针
# define NULL ((void*)0)
# else
# define NULL (0) //如果是c++,则定义NULL为0
# endif
# endif
#endif
#define _IOS_INPUT 1 //定义一些文件标志宏
#define _IOS_OUTPUT 2
#define _IOS_ATEND 4
#define _IOS_APPEND 8
#define _IOS_TRUNC 16
#define _IOS_NOCREATE 32
#define _IOS_NOREPLACE 64
#define _IOS_BIN 128
/* Magic numbers and bits for the _flags field. //魔数的一些位为_flag字段.
The magic numbers use the high-order bits of _flags;
the remaining bits are available for variable flags.
Note: The magic numbers must all be negative if stdio //注意这些魔数必须是相反的,如果stdio仿真是理想的.
emulation is desired. */
#define _IO_MAGIC 0xFBAD0000 /* Magic number */ /
#define _OLD_STDIO_MAGIC 0xFABC0000 /* Emulate old stdio. */
#define _IO_MAGIC_MASK 0xFFFF0000
#define _IO_USER_BUF 1 /* User owns buffer; don't delete it on close. */
#define _IO_UNBUFFERED 2
#define _IO_NO_READS 4 /* Reading not allowed */
#define _IO_NO_WRITES 8 /* Writing not allowd */
#define _IO_EOF_SEEN 0x10
#define _IO_ERR_SEEN 0x20
#define _IO_DELETE_DONT_CLOSE 0x40 /* Don't call close(_fileno) on cleanup. */
#define _IO_LINKED 0x80 /* Set if linked (using _chain) to streambuf::_list_all.*/
#define _IO_IN_BACKUP 0x100
#define _IO_LINE_BUF 0x200
#define _IO_TIED_PUT_GET 0x400 /* Set if put and get pointer logicly tied. */
#define _IO_CURRENTLY_PUTTING 0x800
#define _IO_IS_APPENDING 0x1000
#define _IO_IS_FILEBUF 0x2000
#define _IO_BAD_SEEN 0x4000
#define _IO_USER_LOCK 0x8000
#define _IO_FLAGS2_MMAP 1
#define _IO_FLAGS2_NOTCANCEL 2
#ifdef _LIBC
# define _IO_FLAGS2_FORTIFY 4
#endif
#define _IO_FLAGS2_USER_WBUF 8
#ifdef _LIBC
# define _IO_FLAGS2_SCANF_STD 16
#endif
/* These are "formatting flags" matching the iostream fmtflags enum values. */
//这些都是“格式式标志”相匹配的iostream fmtflags枚举值。
#define _IO_SKIPWS 01
#define _IO_LEFT 02
#define _IO_RIGHT 04
#define _IO_INTERNAL 010
#define _IO_DEC 020
#define _IO_OCT 040
#define _IO_HEX 0100
#define _IO_SHOWBASE 0200
#define _IO_SHOWPOINT 0400
#define _IO_UPPERCASE 01000
#define _IO_SHOWPOS 02000
#define _IO_SCIENTIFIC 04000
#define _IO_FIXED 010000
#define _IO_UNITBUF 020000
#define _IO_STDIO 040000
#define _IO_DONT_CLOSE 0100000
#define _IO_BOOLALPHA 0200000
struct _IO_jump_t; struct _IO_FILE; //两个声明.
/* Handle lock. */ //句柄锁
#ifdef _IO_MTSAFE_IO
# if defined __GLIBC__ && __GLIBC__ >= 2
# include # else
/*# include */
# endif
#else
typedef void _IO_lock_t; //空类型
#endif
/* A streammarker remembers a position in a buffer. */
//一个streammarker记住一个位置在缓冲器。
struct _IO_marker {
struct _IO_marker *_next;
struct _IO_FILE *_sbuf;
/* If _pos >= 0
it points to _buf->Gbase()+_pos. FIXME comment */
/* if _pos < 0, it points to _buf->eBptr()+_pos. FIXME comment */
int _pos;
#if 0 //下面C++语法不可能执行
void set_streampos(streampos sp) { _spos = sp; }
void set_offset(int offset) { _pos = offset; _spos = (streampos)(-2); }
public:
streammarker(streambuf *sb);
~streammarker();
int saving() { return _spos == -2; }
int delta(streammarker&);
int delta();
#endif
};
/* This is the structure from the libstdc++ codecvt class. */ //来自C++库结构的实现
//设计vc的STL库的那位老大P.J.曾经写过这样的一个转换codecvt,来处理wchar,以免写一个wchar就插入一个全0字节
enum __codecvt_result
{
__codecvt_ok,
__codecvt_partial,
__codecvt_error,
__codecvt_noconv
};
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
/* The order of the elements in the following struct must match the order
of the virtual functions in the libstdc++ codecvt class. */
struct _IO_codecvt //方法表
{
void (*__codecvt_destr) (struct _IO_codecvt *);
enum __codecvt_result (*__codecvt_do_out) (struct _IO_codecvt *,
__mbstate_t *,
const wchar_t *,
const wchar_t *,
const wchar_t **, char *,
char *, char **);
enum __codecvt_result (*__codecvt_do_unshift) (struct _IO_codecvt *,
__mbstate_t *, char *,
char *, char **);
enum __codecvt_result (*__codecvt_do_in) (struct _IO_codecvt *,
__mbstate_t *,
const char *, const char *,
const char **, wchar_t *,
wchar_t *, wchar_t **);
int (*__codecvt_do_encoding) (struct _IO_codecvt *);
int (*__codecvt_do_always_noconv) (struct _IO_codecvt *);
int (*__codecvt_do_length) (struct _IO_codecvt *, __mbstate_t *,
const char *, const char *, _IO_size_t);
int (*__codecvt_do_max_length) (struct _IO_codecvt *);
_IO_iconv_t __cd_in;
_IO_iconv_t __cd_out;
};
/* Extra data for wide character streams. */ //为宽字节的流定义的额外的数据
struct _IO_wide_data
{
wchar_t *_IO_read_ptr; /* Current read pointer */ //当前读指针
wchar_t *_IO_read_end; /* End of get area. */ //末尾读指针
wchar_t *_IO_read_base; /* Start of putback+get area. */ //开始读的基偏移
wchar_t *_IO_write_base; /* Start of put area. */
wchar_t *_IO_write_ptr; /* Current put pointer. */ //当前写指针
wchar_t *_IO_write_end; /* End of put area. */
wchar_t *_IO_buf_base; /* Start of reserve area. */
wchar_t *_IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
wchar_t *_IO_save_base; /* Pointer to start of non-current get area. */
wchar_t *_IO_backup_base; /* Pointer to first valid character of
backup area */
wchar_t *_IO_save_end; /* Pointer to end of non-current get area. */
__mbstate_t _IO_state;
__mbstate_t _IO_last_state;
struct _IO_codecvt _codecvt; //实现流的一些转换操作
wchar_t _shortbuf[1];
const struct _IO_jump_t *_wide_vtable;
};
#endif
struct _IO_FILE { //传说中的文件流
int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ //高字是一些魔数,低字是文件标志.
#define _IO_file_flags _flags //定义可以使用_flags宏
/* The following pointers correspond to the C++ streambuf protocol. */ //下面的指针对应的C + + streambuf协议。
/* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
char* _IO_read_ptr; /* Current read pointer */
char* _IO_read_end; /* End of get area. */
char* _IO_read_base; /* Start of putback+get area. */
char* _IO_write_base; /* Start of put area. */
char* _IO_write_ptr; /* Current put pointer. */
char* _IO_write_end; /* End of put area. */
char* _IO_buf_base; /* Start of reserve area. */
char* _IO_buf_end; /* End of reserve area. */
/* The following fields are used to support backing up and undo. */
char *_IO_save_base; /* Pointer to start of non-current get area. */
char *_IO_backup_base; /* Pointer to first valid character of backup area */
char *_IO_save_end; /* Pointer to end of non-current get area. */
struct _IO_marker *_markers;
struct _IO_FILE *_chain; //流链
int _fileno; //文件i_node号
#if 0
int _blksize;
#else
int _flags2; //标志2
#endif
_IO_off_t _old_offset; /* This used to be _offset but it's too small. */ //用来存储偏移,但是太小
#define __HAVE_COLUMN /* temporary */
/* 1+column number of pbase(); 0 is unknown. */
unsigned short _cur_column;
signed char _vtable_offset;
char _shortbuf[1];
/* char* _save_gptr; char* _save_egptr; */
_IO_lock_t *_lock;
#ifdef _IO_USE_OLD_IO_FILE //如果使用旧版本_IO_FILE,则就此结束,否则还下文
};
struct _IO_FILE_complete
{
struct _IO_FILE _file;
#endif
#if defined _G_IO_IO_FILE_VERSION && _G_IO_IO_FILE_VERSION == 0x20001
_IO_off64_t _offset; //如果是新版本则偏移用64位表示
# if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
/* Wide character stream stuff. */
struct _IO_codecvt *_codecvt;
struct _IO_wide_data *_wide_data; //可见新版本直接处理宽字符流
struct _IO_FILE *_freeres_list; //已经释放的链表
void *_freeres_buf;
size_t _freeres_size;
# else
void *__pad1;
void *__pad2;
void *__pad3;
void *__pad4;
size_t __pad5;
# endif
int _mode; //文件模式
/* Make sure we don't get into trouble again. */ //末尾添加足够的位,确保数据安全
char _unused2[15 * sizeof (int) - 4 * sizeof (void *) - sizeof (size_t)];
#endif
};
#ifndef __cplusplus //如果是c++,同样使用这个结构
typedef struct _IO_FILE _IO_FILE;
#endif
struct _IO_FILE_plus;
extern struct _IO_FILE_plus _IO_2_1_stdin_; //定义三个导出变量,三个流文件,可以看下面的_IO_FILE_plus
extern struct _IO_FILE_plus _IO_2_1_stdout_;
extern struct _IO_FILE_plus _IO_2_1_stderr_;
#ifndef _LIBC //如果是LIBC,则定义_IO_stdin等三个变量
#define _IO_stdin ((_IO_FILE*)(&_IO_2_1_stdin_))
#define _IO_stdout ((_IO_FILE*)(&_IO_2_1_stdout_))
#define _IO_stderr ((_IO_FILE*)(&_IO_2_1_stderr_))
#else
extern _IO_FILE *_IO_stdin attribute_hidden; //如果定义则隐藏_IO_stdin,等三个变量
extern _IO_FILE *_IO_stdout attribute_hidden;
extern _IO_FILE *_IO_stderr attribute_hidden;
#endif
/* Functions to do I/O and file management for a stream. */ //下面是的流管理功能
/* Read NBYTES bytes from COOKIE into a buffer pointed to by BUF. //读cookie
Return number of bytes read. */
/ *读取NBYTES字节来自Cookie从一个缓冲区指针到BUF。
返回读到字节数。 * /
typedef __ssize_t __io_read_fn (void *__cookie, char *__buf, size_t __nbytes); //定义一个函数,并不是函数指针
/* Write N bytes pointed to by BUF to COOKIE. Write all N bytes
unless there is an error. Return number of bytes written, or -1 if
there is an error without writing anything. If the file has been
opened for append (__mode.__append set), then set the file pointer
to the end of the file and then do the write; if not, just write at
the current file pointer. */
/ *写N字节指出了从缓冲区到COOKIE里。写所有N字节
除非有一个错误。返回的已经写入字节数,或-1如果
那里有一个错误没有写入东西。如果该文件打开以APPEND方式( __mode设置__append) ,然后设置文件指针
到该文件最后,然后写;如果没有,只写在
当前的文件指针。 * /
typedef __ssize_t __io_write_fn (void *__cookie, __const char *__buf, //写cookie
size_t __n);
/* Move COOKIE's file position to *POS bytes from the
beginning of the file (if W is SEEK_SET),
the current position (if W is SEEK_CUR),
or the end of the file (if W is SEEK_END).
Set *POS to the new file position.
Returns zero if successful, nonzero if not. */
移动COOKIE的文件的位置到* POS处,从
开始的文件(如果W是SEEK_SET ) ,
当前的位置(如果W是SEEK_CUR ) ,
或文件的末尾(如果W是SEEK_END ) 。
设置* POS到新文件的位置。
返回零如果成功的话,如果不是非零。*/
typedef int __io_seek_fn (void *__cookie, _IO_off64_t *__pos, int __w);//定位COOKIE
/* Close COOKIE. */
typedef int __io_close_fn (void *__cookie);//关闭COOKIE
#ifdef _GNU_SOURCE //如果是GNU源代码,就定义下面变量,显然,我们是GNU源代码
/* User-visible names for the above. */
typedef __io_read_fn cookie_read_function_t;
typedef __io_write_fn cookie_write_function_t;
typedef __io_seek_fn cookie_seek_function_t;
typedef __io_close_fn cookie_close_function_t;
/* The structure with the cookie function pointers. */
typedef struct
{
__io_read_fn *read; /* Read bytes. */
__io_write_fn *write; /* Write bytes. */
__io_seek_fn *seek; /* Seek/tell file position. */
__io_close_fn *close; /* Close file. */
} _IO_cookie_io_functions_t;
typedef _IO_cookie_io_functions_t cookie_io_functions_t;
struct _IO_cookie_file;
/* Initialize one of those. */ //初始化上面变量
extern void _IO_cookie_init (struct _IO_cookie_file *__cfile, int __read_write,
void *__cookie, _IO_cookie_io_functions_t __fns);
#endif
#ifdef __cplusplus //如果是c++
extern "C" {
#endif
extern int __underflow (_IO_FILE *); //下溢
extern int __uflow (_IO_FILE *); //溢出
extern int __overflow (_IO_FILE *, int); //上溢
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T //如果是wchar版本,新版本
extern _IO_wint_t __wunderflow (_IO_FILE *);
extern _IO_wint_t __wuflow (_IO_FILE *);
extern _IO_wint_t __woverflow (_IO_FILE *, _IO_wint_t);
#endif
#if __GNUC__ >= 3
# define _IO_BE(expr, res) __builtin_expect ((expr), res)
#else
# define _IO_BE(expr, res) (expr)
#endif
//以下这些定义十分的重要,标准库很多复杂功能都是来自于下面宏.
//下面每个宏几乎是一个函数,libio里文件大都在这些基础上实现
#define _IO_getc_unlocked(_fp) \
(_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) \ //比较当前读指针,大于等末读指针尾溢出,返回新的指针,具体看下篇
? __uflow (_fp) : *(unsigned char *) (_fp)->_IO_read_ptr++)
#define _IO_peekc_unlocked(_fp) \ //同上,但判断还加上是否文件尾
(_IO_BE ((_fp)->_IO_read_ptr >= (_fp)->_IO_read_end, 0) \
&& __underflow (_fp) == EOF ? EOF \
: *(unsigned char *) (_fp)->_IO_read_ptr)
#define _IO_putc_unlocked(_ch, _fp) \ //将写ch,写到fp里,并返回当前
(_IO_BE ((_fp)->_IO_write_ptr >= (_fp)->_IO_write_end, 0) \
? __overflow (_fp, (unsigned char) (_ch)) \
: (unsigned char) (*(_fp)->_IO_write_ptr++ = (_ch)))
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
# define _IO_getwc_unlocked(_fp) \ //宽字节,具体实现同上
(_IO_BE ((_fp)->_wide_data->_IO_read_ptr >= (_fp)->_wide_data->_IO_read_end,\
0) \
? __wuflow (_fp) : (_IO_wint_t) *(_fp)->_wide_data->_IO_read_ptr++)
# define _IO_putwc_unlocked(_wch, _fp) \
(_IO_BE ((_fp)->_wide_data->_IO_write_ptr \
>= (_fp)->_wide_data->_IO_write_end, 0) \
? __woverflow (_fp, _wch) \
: (_IO_wint_t) (*(_fp)->_wide_data->_IO_write_ptr++ = (_wch)))
#endif
#define _IO_feof_unlocked(__fp) (((__fp)->_flags & _IO_EOF_SEEN) != 0) //是否文件结束
#define _IO_ferror_unlocked(__fp) (((__fp)->_flags & _IO_ERR_SEEN) != 0) //判断标志,是否出错
extern int _IO_getc (_IO_FILE *__fp); //在libio实现,看下篇
extern int _IO_putc (int __c, _IO_FILE *__fp);
extern int _IO_feof (_IO_FILE *__fp) __THROW;
extern int _IO_ferror (_IO_FILE *__fp) __THROW;
extern int _IO_peekc_locked (_IO_FILE *__fp);
/* This one is for Emacs. */
#define _IO_PENDING_OUTPUT_COUNT(_fp) \
((_fp)->_IO_write_ptr - (_fp)->_IO_write_base)
extern void _IO_flockfile (_IO_FILE *) __THROW;
extern void _IO_funlockfile (_IO_FILE *) __THROW;
extern int _IO_ftrylockfile (_IO_FILE *) __THROW;
#ifdef _IO_MTSAFE_IO
# define _IO_peekc(_fp) _IO_peekc_locked (_fp)
# define _IO_flockfile(_fp) \
if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_flockfile (_fp)
# define _IO_funlockfile(_fp) \
if (((_fp)->_flags & _IO_USER_LOCK) == 0) _IO_funlockfile (_fp)
#else
# define _IO_peekc(_fp) _IO_peekc_unlocked (_fp)
# define _IO_flockfile(_fp) /**/
# define _IO_funlockfile(_fp) /**/
# define _IO_ftrylockfile(_fp) /**/
# define _IO_cleanup_region_start(_fct, _fp) /**/
# define _IO_cleanup_region_end(_Doit) /**/
#endif /* !_IO_MTSAFE_IO */
//当然这些函数也来自于libio目录下的其他文件
extern int _IO_vfscanf (_IO_FILE * __restrict, const char * __restrict,
_IO_va_list, int *__restrict);
extern int _IO_vfprintf (_IO_FILE *__restrict, const char *__restrict,
_IO_va_list);
extern _IO_ssize_t _IO_padn (_IO_FILE *, int, _IO_ssize_t);
extern _IO_size_t _IO_sgetn (_IO_FILE *, void *, _IO_size_t);
extern _IO_off64_t _IO_seekoff (_IO_FILE *, _IO_off64_t, int, int);
extern _IO_off64_t _IO_seekpos (_IO_FILE *, _IO_off64_t, int);
extern void _IO_free_backup_area (_IO_FILE *) __THROW;
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
extern _IO_wint_t _IO_getwc (_IO_FILE *__fp);
extern _IO_wint_t _IO_putwc (wchar_t __wc, _IO_FILE *__fp);
extern int _IO_fwide (_IO_FILE *__fp, int __mode) __THROW; ///看上面fwide函数
# if __GNUC__ >= 2
/* While compiling glibc we have to handle compatibility with very old
versions. */
# if defined _LIBC && defined SHARED
# include # if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
# define _IO_fwide_maybe_incompatible \ //是否是宽字节的,fwide用到它
(__builtin_expect (&_IO_stdin_used == NULL, 0))
extern const int _IO_stdin_used;
weak_extern (_IO_stdin_used);
# endif
# endif
# ifndef _IO_fwide_maybe_incompatible
# define _IO_fwide_maybe_incompatible (0)
# endif
/* A special optimized version of the function above. It optimizes the
case of initializing an unoriented byte stream. */
# define _IO_fwide(__fp, __mode) \ //改变流模式这里已经实现了
({ int __result = (__mode); \
if (__result < 0 && ! _IO_fwide_maybe_incompatible) \
{ \
if ((__fp)->_mode == 0) \
/* We know that all we have to do is to set the flag. */ \
(__fp)->_mode = -1; \
__result = (__fp)->_mode; \
} \
else if (__builtin_constant_p (__mode) && (__mode) == 0) \
__result = _IO_fwide_maybe_incompatible ? -1 : (__fp)->_mode; \
else \
__result = _IO_fwide (__fp, __result); \
__result; })
# endif
extern int _IO_vfwscanf (_IO_FILE * __restrict, const wchar_t * __restrict,
_IO_va_list, int *__restrict);
extern int _IO_vfwprintf (_IO_FILE *__restrict, const wchar_t *__restrict,
_IO_va_list);
extern _IO_ssize_t _IO_wpadn (_IO_FILE *, wint_t, _IO_ssize_t);
extern void _IO_free_wbackup_area (_IO_FILE *) __THROW;
#endif
#ifdef __LDBL_COMPAT
# include #endif
#ifdef __cplusplus
}
#endif
#endif /* _IO_STDIO_H */