Язык программирования C



         

Пример - реализация функций FOPEN и GETC - часть 3


функция _filebuf несколько более сложная. Основная трудность заключается в том, что _filebuf стремится разрешить доступ к файлу и в том случае, когда может не оказаться достаточно места в памяти для буферизации ввода или вывода. если пространство для нового буфера может быть получено обращением к функции calloc, то все отлично; если же нет, то _filebuf осуществляет небуферизованный ввод/вывод, используя отдельный символ, помещенный в локальном массиве.

#include <stdio.h> _fillbuf(fp) /*allocate and fill input buffer*/ register file *fp; ( static char smallbuf(nfile);/*for unbuffered 1/0*/ char *calloc(); if((fr->_flag& _read)==0 || (fp->_flag&(EOF|_err)) |=0 return(EOF); while(fp->_base==null) /*find buffer space*/ if(fp->_flag & _unbuf) /*unbuffered*/ fp->_base=&smallbuf[fp->_fd]; else if((fp->_base=calloc(_bufsize,1))==null) fp->_flag |=_unbuf; /*can't get big buf*/ else fp->_flag |=_bigbuf; /*got big one*/ fp->_ptr=fp->_base; fp->_cnt=read(fp->_fd, fp->_ptr, fp->_flag & _unbuf ? 1 : _bufsize); ff(--fp->_cnt<0) { if(fp->_cnt== -1) fp->_flag | = _EOF; else fp->_flag |= _ err; fp->_cnt = 0; return(EOF); } return(*fp->_ptr++ & 0377); /*make char positive*/ }

При первом обращении к getc для конкретного файла счетчик оказывается равным нулю, что приводит к обращению к _filebuf. Если функция _filebuf найдет, что этот файл не открыт для чтения, она немедленно возвращает EOF. В противном случае она пытается выделить большой буфер, а если ей это не удается, то буфер из одного символа. При этом она заносит в _flag соответствующую информацию о буферизации.

Раз буфер уже создан, функция _filebuf просто вызывает функцию read для его заполнения, устанавливает счетчик и указатели и возвращает символ из начала буфера.

Единственный оставшийся невыясненным вопрос состоит в том, как все начинается. Массив _iob должен быть определен и инициализирован для stdin, stdout и stderr:

file _iob[nfile] = { (null,0,_read,0), /*stdin*/ (null,0,null,1), /*stdout*/ (null,0,null,_write | _unbuf,2) /*stderr*/ };




Содержание  Назад  Вперед