fgetcの行方

前回の続きで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$ 

なるほど、当たり前なんですが、バッファの管理情報ですね。
意外に簡単な作りであることに衝撃。先人たちが作った神がかったシンプルな設計なんでしょう。

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA