fgets 함수이다.
이름에서부터 알 수 있듯이, 파일에서 데이터를 get 하는 함수이다.
소스코드는 다음과 같다.
_IO_fgets
char *
_IO_fgets (char *buf, int n, FILE *fp)
{
size_t count;
char *result;
int old_error;
CHECK_FILE (fp, NULL);
if (n <= 0)
return NULL;
if (__glibc_unlikely (n == 1))
{
/* Another irregular case: since we have to store a NUL byte and
there is only room for exactly one byte, we don't have to
read anything. */
buf[0] = '\0';
return buf;
}
_IO_acquire_lock (fp);
/* This is very tricky since a file descriptor may be in the
non-blocking mode. The error flag doesn't mean much in this
case. We return an error only when there is a new error. */
old_error = fp->_flags & _IO_ERR_SEEN;
fp->_flags &= ~_IO_ERR_SEEN;
count = _IO_getline (fp, buf, n - 1, '\n', 1);
/* If we read in some bytes and errno is EAGAIN, that error will
be reported for next read. */
if (count == 0 || ((fp->_flags & _IO_ERR_SEEN) && errno != EAGAIN))
result = NULL;
else
{
buf[count] = '\0';
result = buf;
}
fp->_flags |= old_error;
_IO_release_lock (fp);
return result;
}
weak_alias (_IO_fgets, fgets)
함수도 복잡하지 않다.
바로 _IO_getline
함수를 호출하는 것을 알 수 있다. 바로 살펴보자.
_IO_getline
size_t
_IO_getline (FILE *fp, char *buf, size_t n, int delim,
int extract_delim)
{
return _IO_getline_info (fp, buf, n, delim, extract_delim, (int *) 0);
}
libc_hidden_def (_IO_getline)
/* Algorithm based on that used by Berkeley pre-4.4 fgets implementation.
Read chars into buf (of size n), until delim is seen.
Return number of chars read (at most n).
Does not put a terminating '\0' in buf.
If extract_delim < 0, leave delimiter unread.
If extract_delim > 0, insert delim in output. */
size_t
_IO_getline_info (FILE *fp, char *buf, size_t n, int delim,
int extract_delim, int *eof)
{
char *ptr = buf;
if (eof != NULL)
*eof = 0;
if (__builtin_expect (fp->_mode, -1) == 0)
_IO_fwide (fp, -1);
while (n != 0)
{
ssize_t len = fp->_IO_read_end - fp->_IO_read_ptr;
if (len <= 0)
{
int c = __uflow (fp);
if (c == EOF)
{
if (eof)
*eof = c;
break;
}
if (c == delim)
{
if (extract_delim > 0)
*ptr++ = c;
else if (extract_delim < 0)
_IO_sputbackc (fp, c);
if (extract_delim > 0)
++len;
return ptr - buf;
}
*ptr++ = c;
n--;
}
else
{
char *t;
if ((size_t) len >= n)
len = n;
t = (char *) memchr ((void *) fp->_IO_read_ptr, delim, len);
if (t != NULL)
{
size_t old_len = ptr-buf;
len = t - fp->_IO_read_ptr;
if (extract_delim >= 0)
{
++t;
if (extract_delim > 0)
++len;
}
memcpy ((void *) ptr, (void *) fp->_IO_read_ptr, len);
fp->_IO_read_ptr = t;
return old_len + len;
}
memcpy ((void *) ptr, (void *) fp->_IO_read_ptr, len);
fp->_IO_read_ptr += len;
ptr += len;
n -= len;
}
}
return ptr - buf;
}
libc_hidden_def (_IO_getline_info)
만약 len <= 0 이라면 __uflow
를 호출하는 것을 알 수 있다.
앞의 fread함수에서의 동작과 비교해 보자.
_IO_xsgetn
__underflow
_IO_file_underflow
_IO_fgets
__uflow
_IO_default_uflow
_IO_file_underflow
결국 fread와 같이 _IO_file_underflow
를 호출하게 된다. 다만, gets함수이므로 중간에 개행이 나오면 멈춘다는 차이점은 존재한다.