internals.c

来自「一个C源代码分析器」· C语言 代码 · 共 660 行 · 第 1/2 页

C
660
字号
	  char cc = (unsigned char) c;	  if ((*fp->__io_funcs.__write)(fp->__cookie, &cc, 1) < 1)	    fp->__error = 1;	  else	    {	      /* Record that we've moved forward in the file.  */	      ++fp->__offset;	      ++fp->__target;	    }	}      else	/* Just put C in the buffer.  */	*fp->__bufp++ = (unsigned char) c;    } end:  if (!twiddled)    {      /* The new target position moves up as	 much as the user wrote into the buffer.  */      fp->__target += buffer_written;      /* Set the reading limit to the beginning of the buffer,	 so the next `getc' will call __fillbf.  */      fp->__get_limit = fp->__buffer;    }  if (feof(fp) || ferror(fp))    fp->__bufp = fp->__put_limit;}/* Fill the buffer for FP and return the first character read (or EOF).   This is the default `input_room' function.  */static intDEFUN(fillbuf, (fp), register FILE *fp){  /* How far into the buffer we read we want to start bufp.  */  size_t buffer_offset = 0;  register char *buffer;  register size_t to_read, nread = 0;  /* This must be unsigned to avoid sign extension in return.  */  unsigned char c;  if (fp->__io_funcs.__read == NULL)    {      /* There is no read function, so always return EOF.  */      fp->__eof = 1;      goto end;    }  if (fp->__buffer == NULL)    {      /* We're unbuffered, so we want to read only one character.  */      buffer = (char *) &c;      to_read = 1;    }  else    {      /* We're buffered, so try to fill the buffer.  */      buffer = fp->__buffer;      to_read = fp->__bufsize;    }  /* We're reading, so we're not at the end-of-file.  */  fp->__eof = 0;  /* Go to the target file position.  */  {    int save = errno;    if (__stdio_check_offset (fp) == 0 && fp->__target != fp->__offset)      {	/* Move to a block (buffer size) boundary.  */	if (fp->__bufsize != 0)	  {	    buffer_offset = fp->__target % fp->__bufsize;	    fp->__target -= buffer_offset;	  }	seek_to_target (fp);      }    errno = save;  }  while (!ferror(fp) && !feof(fp) && nread <= buffer_offset)    {      /* Try to fill the buffer.  */      int count = (*fp->__io_funcs.__read)(fp->__cookie, buffer, to_read);      if (count == 0)	fp->__eof = 1;      else if (count < 0)	fp->__error = 1;      else	{	  buffer += count;	  nread += count;	  to_read -= count;	  /* Record that we've moved forward in the file.  */	  fp->__offset += count;	}    }  if (fp->__buffer == NULL)    /* There is no buffer, so return the character we read       without all the buffer pointer diddling.  */    return (feof(fp) || ferror(fp)) ? EOF : c;  /* Reset the buffer pointer to the beginning of the buffer     (plus whatever offset we may have set above).  */  fp->__bufp = fp->__buffer + buffer_offset; end:;  if (feof(fp) || ferror(fp))    {      /* Set both end pointers to the beginning of the buffer so	 the next i/o call will force a call to __fillbf/__flshfp.  */      fp->__put_limit = fp->__get_limit = fp->__buffer;      return EOF;    }  /* Set the end pointer to one past the last character we read.  */  fp->__get_limit = fp->__buffer + nread;  /* Make it so the next `putc' will call __flshfp.  */  fp->__put_limit = fp->__buffer;  /* Return the first character in the buffer.  */  return *((unsigned char *) (fp->__bufp++));}/* Default I/O and room functions.  */extern __io_read_fn __stdio_read;extern __io_write_fn __stdio_write;extern __io_seek_fn __stdio_seek;extern __io_close_fn __stdio_close;extern __io_fileno_fn __stdio_fileno;CONST __io_functions __default_io_functions =  {    __stdio_read, __stdio_write, __stdio_seek, __stdio_close, __stdio_fileno  };CONST __room_functions __default_room_functions =  {    fillbuf, flushbuf  };/* Flush the buffer for FP and also write C if FLUSH_ONLY is nonzero.   This is the function used by putc and fflush.  */intDEFUN(__flshfp, (fp, c),      register FILE *fp AND int c){  int flush_only = c == EOF;  if (!__validfp(fp) || !fp->__mode.__write)    {      errno = EINVAL;      return EOF;    }  if (ferror(fp))    return EOF;  if (fp->__pushed_back)    {      /* Discard the char pushed back by ungetc.  */      fp->__bufp = fp->__pushback_bufp;      fp->__pushed_back = 0;    }  /* Make sure the stream is initialized (has functions and buffering).  */  init_stream(fp);  /* Do this early, so a `putc' on such a stream will never return success.  */  if (fp->__room_funcs.__output == NULL)    {      /* A NULL `output room' function means	 to always return an output error.  */      fp->__error = 1;      return EOF;    }  if (!flush_only &&      /* Will C fit into the buffer?	 See below about linebuf_active.  */      fp->__bufp < (fp->__linebuf_active ? fp->__buffer + fp->__bufsize :		    fp->__put_limit))    {      /* The character will fit in the buffer, so put it there.  */      *fp->__bufp++ = (unsigned char) c;      if (fp->__linebuf && (unsigned char) c == '\n')	flush_only = 1;      else	return (unsigned char) c;    }  if (fp->__linebuf_active)    /* This is an active line-buffered stream, so its put-limit is set       to the beginning of the buffer in order to force a __flshfp call       on each putc (see below).  We undo this hack here (by setting       the limit to the end of the buffer) to simplify the interface       with the output-room function.  */    fp->__put_limit = fp->__buffer + fp->__bufsize;  /* Make room in the buffer.  */  (*fp->__room_funcs.__output) (fp, flush_only ? EOF : (unsigned char) c);  if (fp->__linebuf)    {      /* This is a line-buffered stream, and it is now ready to do	 some output.  We call this an "active line-buffered stream".	 We set the put_limit to the beginning of the buffer,	 so the next `putc' call will force a call to this function.	 Setting the linebuf_active flag tells the code above	 (on the next call) to undo this hackery.  */      fp->__put_limit = fp->__buffer;      fp->__linebuf_active = 1;    }  if (ferror (fp))    return EOF;  if (flush_only)    return 0;  return (unsigned char) c;}/* Fill the buffer for FP and return the first character read.   This is the function used by getc.  */intDEFUN(__fillbf, (fp), register FILE *fp){  register int c;  fpos_t new_target;  if (!__validfp(fp) || !fp->__mode.__read)    {      errno = EINVAL;      return EOF;    }  if (fp->__pushed_back)    {      /* Return the char pushed back by ungetc.  */      fp->__bufp = fp->__pushback_bufp;      fp->__pushed_back = 0;      return fp->__pushback;    }  /* Make sure the stream is initialized (has functions and buffering). */  init_stream(fp);  /* If we're trying to read the first character of a new     line of input from an unbuffered or line buffered stream,     we must flush all line-buffered output streams. */  if (fp->__buffer == NULL || fp->__linebuf)    {      register FILE *f;      for (f = __stdio_head; f != NULL; f = f->__next)	if (__validfp (f) && f->__linebuf && f->__mode.__write)	  (void) __flshfp (f, EOF);    }  /* Note we must do this after flushing all line-buffered     streams, or else __flshfp would undo it!  */  if (fp->__linebuf_active)    {      /* This is an active line-buffered stream, meaning it is in the midst	 of writing, but has a bogus put_limit.  Restore it to normality.  */      fp->__put_limit = fp->__buffer + fp->__bufsize;      fp->__linebuf_active = 0;    }  /* We want the beginning of the buffer to now     map to just past the last data we read.  */  new_target = fp->__target + (fp->__get_limit - fp->__buffer);  if (fp->__put_limit > fp->__buffer)    {      /* There is written data in the buffer.	 Flush it out.  */      if (fp->__room_funcs.__output == NULL)	fp->__error = 1;      else	(*fp->__room_funcs.__output) (fp, EOF);    }  fp->__target = new_target;  if (ferror(fp))    c = EOF;  else if (fp->__room_funcs.__input != NULL)    {      c = (*fp->__room_funcs.__input)(fp);      if (fp->__buffer == NULL)	/* This is an unbuffered stream, so the target sync above	   won't do anything the next time around.  Instead, note that	   we have read one character.  The (nonexistent) buffer now	   maps to the position just past that character.  */	++fp->__target;    }  else    {      /* A NULL `input_room' function means always return EOF.  */      fp->__eof = 1;      c = EOF;    }  return c;}/* Nuke a stream, but don't kill its link in the chain.  */voidDEFUN(__invalidate, (stream), register FILE *stream){  /* Save its link.  */  register FILE *next = stream->__next;  /* Pulverize the fucker.  */  memset((PTR) stream, 0, sizeof(FILE));  /* Restore the deceased's link.  */  stream->__next = next;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?