前回の続きでfgetcの行方を追います。fgetc.c自体はずっと前に削除されていることがわかりましたが(debian)、
代わりに何が使われているかというと_IO_getcでした。
_IO_getcはlibio/getc.cに定義されているので全文。
takk@deb9:~/src/glibc-2.24$ cat -n libio/getc.c 1 /* Copyright (C) 1993-2016 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 4 The GNU C Library is free software; you can redistribute it and/or 5 modify it under the terms of the GNU Lesser General Public 6 License as published by the Free Software Foundation; either 7 version 2.1 of the License, or (at your option) any later version. 8 9 The GNU C Library is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Lesser General Public License for more details. 13 14 You should have received a copy of the GNU Lesser General Public 15 License along with the GNU C Library; if not, see 16 <http://www.gnu.org/licenses/>. 17 18 As a special exception, if you link the code in this file with 19 files compiled with a GNU compiler to produce an executable, 20 that does not cause the resulting executable to be covered by 21 the GNU Lesser General Public License. This exception does not 22 however invalidate any other reasons why the executable file 23 might be covered by the GNU Lesser General Public License. 24 This exception applies to code released by its copyright holders 25 in files containing the exception. */ 26 27 #include "libioP.h" 28 #include "stdio.h" 29 30 #undef _IO_getc 31 32 int 33 _IO_getc (FILE *fp) 34 { 35 int result; 36 CHECK_FILE (fp, EOF); 37 _IO_acquire_lock (fp); 38 result = _IO_getc_unlocked (fp); 39 _IO_release_lock (fp); 40 return result; 41 } 42 43 #undef getc 44 45 #ifdef weak_alias 46 weak_alias (_IO_getc, getc) 47 weak_alias (_IO_getc, fgetc) 48 49 #ifndef _IO_MTSAFE_IO 50 #undef getc_unlocked 51 weak_alias (_IO_getc, getc_unlocked) 52 weak_alias (_IO_getc, fgetc_unlocked) 53 #endif 54 #endif takk@deb9:~/src/glibc-2.24$
32~41行目がそうですね。
内部では、_IO_getc_unlockedが使われていました。
それも検索。
takk@deb9:~/src/glibc-2.24$ grep -r _IO_getc_unlocked * ChangeLog.14: * libio/libio.h: Use __builtin_expect in _IO_getc_unlocked, ChangeLog.6: _IO_getc_unlocked. debug/gets_chk.c: ch = _IO_getc_unlocked (_IO_stdin); libio/getc.c: result = _IO_getc_unlocked (fp); libio/getchar_u.c: return _IO_getc_unlocked (_IO_stdin); libio/libio.h:#define _IO_getc_unlocked(_fp) \ libio/bits/stdio.h: return _IO_getc_unlocked (__fp); libio/bits/stdio.h: return _IO_getc_unlocked (__fp); libio/bits/stdio.h: return _IO_getc_unlocked (stdin); libio/bits/stdio.h: int __c = _IO_getc_unlocked (__stream); \ libio/bits/stdio2.h: int __c = _IO_getc_unlocked (__stream); libio/iogets.c: ch = _IO_getc_unlocked (_IO_stdin); libio/getchar.c: result = _IO_getc_unlocked (_IO_stdin); libio/getc_u.c: return _IO_getc_unlocked (fp); stdio-common/vfscanf.c: : ((c = _IO_getc_unlocked (s)), \ tags:_IO_getc_unlocked libio/libio.h 400;" d takk@deb9:~/src/glibc-2.24$
libio/libio.hの#defineで定義されています。マクロだったんですね。
定義されている箇所を見てみます。
takk@deb9:~/src/glibc-2.24$ grep -A5 _IO_getc_unlocked libio/libio.h #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 \ takk@deb9:~/src/glibc-2.24$
_fpを操作しているだけなので、結局のところ、FILEポインタを見れば良さそうです。
FILEをgrepするとどのくらヒットするでしょうか。
takk@deb9:~/src/glibc-2.24$ grep -r FILE * | wc -l 6742 takk@deb9:~/src/glibc-2.24$
さすがにこの数を探すのは面倒なので、globalやctagsあたりでさっと見た方がよいでしょう。
ctagsを打って、Vimを起動します。
takk@deb9:~/src/glibc-2.24$ ctags -R * takk@deb9:~/src/glibc-2.24$ vim
Vimから 定義場所を開きます。
:ta FILE
typedefしている箇所がエディタで開きますので、
47 /* The opaque type of streams. This is the definition u 48 typedef struct _IO_FILE FILE; 49 __END_NAMESPACE_STD 50 #if defined __USE_LARGEFILE64 || defined __USE_POSIX \
_IO_FILEにカーソルを移動した後、CTRL+”]”を押して定義場所へ移動します。
libio/libio.hでした。知ってれば直接このファイルに来ますけどね。
ということでFILE構造体を見てみます。
takk@deb9:~/src/glibc-2.24$ cat -n libio/libio.h | sed -ne '241,282p' 241 struct _IO_FILE { 242 int _flags; /* High-order word is _IO_MAGIC; rest is flags. */ 243 #define _IO_file_flags _flags 244 245 /* The following pointers correspond to the C++ streambuf protocol. */ 246 /* Note: Tk uses the _IO_read_ptr and _IO_read_end fields directly. */ 247 char* _IO_read_ptr; /* Current read pointer */ 248 char* _IO_read_end; /* End of get area. */ 249 char* _IO_read_base; /* Start of putback+get area. */ 250 char* _IO_write_base; /* Start of put area. */ 251 char* _IO_write_ptr; /* Current put pointer. */ 252 char* _IO_write_end; /* End of put area. */ 253 char* _IO_buf_base; /* Start of reserve area. */ 254 char* _IO_buf_end; /* End of reserve area. */ 255 /* The following fields are used to support backing up and undo. */ 256 char *_IO_save_base; /* Pointer to start of non-current get area. */ 257 char *_IO_backup_base; /* Pointer to first valid character of backup area */ 258 char *_IO_save_end; /* Pointer to end of non-current get area. */ 259 260 struct _IO_marker *_markers; 261 262 struct _IO_FILE *_chain; 263 264 int _fileno; 265 #if 0 266 int _blksize; 267 #else 268 int _flags2; 269 #endif 270 _IO_off_t _old_offset; /* This used to be _offset but it's too small. */ 271 272 #define __HAVE_COLUMN /* temporary */ 273 /* 1+column number of pbase(); 0 is unknown. */ 274 unsigned short _cur_column; 275 signed char _vtable_offset; 276 char _shortbuf[1]; 277 278 /* char* _save_gptr; char* _save_egptr; */ 279 280 _IO_lock_t *_lock; 281 #ifdef _IO_USE_OLD_IO_FILE 282 }; takk@deb9:~/src/glibc-2.24$
なるほど、当たり前なんですが、バッファの管理情報ですね。
意外に簡単な作りであることに衝撃。先人たちが作った神がかったシンプルな設計なんでしょう。
コメント