OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [newlib-1.17.0/] [newlib/] [libc/] [stdio/] [ungetc.c] - Diff between revs 148 and 158

Only display areas with differences | Details | Blame | View Log

Rev 148 Rev 158
/*
/*
 * Copyright (c) 1990 The Regents of the University of California.
 * Copyright (c) 1990 The Regents of the University of California.
 * All rights reserved.
 * All rights reserved.
 *
 *
 * Redistribution and use in source and binary forms are permitted
 * Redistribution and use in source and binary forms are permitted
 * provided that the above copyright notice and this paragraph are
 * provided that the above copyright notice and this paragraph are
 * duplicated in all such forms and that any documentation,
 * duplicated in all such forms and that any documentation,
 * advertising materials, and other materials related to such
 * advertising materials, and other materials related to such
 * distribution and use acknowledge that the software was developed
 * distribution and use acknowledge that the software was developed
 * by the University of California, Berkeley.  The name of the
 * by the University of California, Berkeley.  The name of the
 * University may not be used to endorse or promote products derived
 * University may not be used to endorse or promote products derived
 * from this software without specific prior written permission.
 * from this software without specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
 */
/*
/*
FUNCTION
FUNCTION
<<ungetc>>---push data back into a stream
<<ungetc>>---push data back into a stream
 
 
INDEX
INDEX
        ungetc
        ungetc
INDEX
INDEX
        _ungetc_r
        _ungetc_r
 
 
ANSI_SYNOPSIS
ANSI_SYNOPSIS
        #include <stdio.h>
        #include <stdio.h>
        int ungetc(int <[c]>, FILE *<[stream]>);
        int ungetc(int <[c]>, FILE *<[stream]>);
 
 
        int _ungetc_r(struct _reent *<[reent]>, int <[c]>, FILE *<[stream]>);
        int _ungetc_r(struct _reent *<[reent]>, int <[c]>, FILE *<[stream]>);
 
 
DESCRIPTION
DESCRIPTION
<<ungetc>> is used to return bytes back to <[stream]> to be read again.
<<ungetc>> is used to return bytes back to <[stream]> to be read again.
If <[c]> is EOF, the stream is unchanged.  Otherwise, the unsigned
If <[c]> is EOF, the stream is unchanged.  Otherwise, the unsigned
char <[c]> is put back on the stream, and subsequent reads will see
char <[c]> is put back on the stream, and subsequent reads will see
the bytes pushed back in reverse order.  Pushed byes are lost if the
the bytes pushed back in reverse order.  Pushed byes are lost if the
stream is repositioned, such as by <<fseek>>, <<fsetpos>>, or
stream is repositioned, such as by <<fseek>>, <<fsetpos>>, or
<<rewind>>.
<<rewind>>.
 
 
The underlying file is not changed, but it is possible to push back
The underlying file is not changed, but it is possible to push back
something different than what was originally read.  Ungetting a
something different than what was originally read.  Ungetting a
character will clear the end-of-stream marker, and decrement the file
character will clear the end-of-stream marker, and decrement the file
position indicator.  Pushing back beyond the beginning of a file gives
position indicator.  Pushing back beyond the beginning of a file gives
unspecified behavior.
unspecified behavior.
 
 
The alternate function <<_ungetc_r>> is a reentrant version.  The
The alternate function <<_ungetc_r>> is a reentrant version.  The
extra argument <[reent]> is a pointer to a reentrancy structure.
extra argument <[reent]> is a pointer to a reentrancy structure.
 
 
RETURNS
RETURNS
The character pushed back, or <<EOF>> on error.
The character pushed back, or <<EOF>> on error.
 
 
PORTABILITY
PORTABILITY
ANSI C requires <<ungetc>>, but only requires a pushback buffer of one
ANSI C requires <<ungetc>>, but only requires a pushback buffer of one
byte; although this implementation can handle multiple bytes, not all
byte; although this implementation can handle multiple bytes, not all
can.  Pushing back a signed char is a common application bug.
can.  Pushing back a signed char is a common application bug.
 
 
Supporting OS subroutines required: <<sbrk>>.
Supporting OS subroutines required: <<sbrk>>.
*/
*/
 
 
#if defined(LIBC_SCCS) && !defined(lint)
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "%W% (Berkeley) %G%";
static char sccsid[] = "%W% (Berkeley) %G%";
#endif /* LIBC_SCCS and not lint */
#endif /* LIBC_SCCS and not lint */
 
 
#include <_ansi.h>
#include <_ansi.h>
#include <reent.h>
#include <reent.h>
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include "local.h"
#include "local.h"
 
 
/*
/*
 * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
 * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
 * the buffer moves, so that it points the same distance from the end,
 * the buffer moves, so that it points the same distance from the end,
 * and move the bytes in the buffer around as necessary so that they
 * and move the bytes in the buffer around as necessary so that they
 * are all at the end (stack-style).
 * are all at the end (stack-style).
 */
 */
 
 
/*static*/
/*static*/
int
int
_DEFUN(__submore, (rptr, fp),
_DEFUN(__submore, (rptr, fp),
       struct _reent *rptr _AND
       struct _reent *rptr _AND
       register FILE *fp)
       register FILE *fp)
{
{
  register int i;
  register int i;
  register unsigned char *p;
  register unsigned char *p;
 
 
  if (fp->_ub._base == fp->_ubuf)
  if (fp->_ub._base == fp->_ubuf)
    {
    {
      /*
      /*
       * Get a new buffer (rather than expanding the old one).
       * Get a new buffer (rather than expanding the old one).
       */
       */
      if ((p = (unsigned char *) _malloc_r (rptr, (size_t) BUFSIZ)) == NULL)
      if ((p = (unsigned char *) _malloc_r (rptr, (size_t) BUFSIZ)) == NULL)
        return EOF;
        return EOF;
      fp->_ub._base = p;
      fp->_ub._base = p;
      fp->_ub._size = BUFSIZ;
      fp->_ub._size = BUFSIZ;
      p += BUFSIZ - sizeof (fp->_ubuf);
      p += BUFSIZ - sizeof (fp->_ubuf);
      for (i = sizeof (fp->_ubuf); --i >= 0;)
      for (i = sizeof (fp->_ubuf); --i >= 0;)
        p[i] = fp->_ubuf[i];
        p[i] = fp->_ubuf[i];
      fp->_p = p;
      fp->_p = p;
      return 0;
      return 0;
    }
    }
  i = fp->_ub._size;
  i = fp->_ub._size;
  p = (unsigned char *) _realloc_r (rptr, (_PTR) (fp->_ub._base), i << 1);
  p = (unsigned char *) _realloc_r (rptr, (_PTR) (fp->_ub._base), i << 1);
  if (p == NULL)
  if (p == NULL)
    return EOF;
    return EOF;
  _CAST_VOID memcpy ((_PTR) (p + i), (_PTR) p, (size_t) i);
  _CAST_VOID memcpy ((_PTR) (p + i), (_PTR) p, (size_t) i);
  fp->_p = p + i;
  fp->_p = p + i;
  fp->_ub._base = p;
  fp->_ub._base = p;
  fp->_ub._size = i << 1;
  fp->_ub._size = i << 1;
  return 0;
  return 0;
}
}
 
 
int
int
_DEFUN(_ungetc_r, (rptr, c, fp),
_DEFUN(_ungetc_r, (rptr, c, fp),
       struct _reent *rptr _AND
       struct _reent *rptr _AND
       int c               _AND
       int c               _AND
       register FILE *fp)
       register FILE *fp)
{
{
  if (c == EOF)
  if (c == EOF)
    return (EOF);
    return (EOF);
 
 
  /* Ensure stdio has been initialized.
  /* Ensure stdio has been initialized.
     ??? Might be able to remove this as some other stdio routine should
     ??? Might be able to remove this as some other stdio routine should
     have already been called to get the char we are un-getting.  */
     have already been called to get the char we are un-getting.  */
 
 
  CHECK_INIT (rptr, fp);
  CHECK_INIT (rptr, fp);
 
 
  _flockfile (fp);
  _flockfile (fp);
 
 
  ORIENT (fp, -1);
  ORIENT (fp, -1);
 
 
  /* After ungetc, we won't be at eof anymore */
  /* After ungetc, we won't be at eof anymore */
  fp->_flags &= ~__SEOF;
  fp->_flags &= ~__SEOF;
 
 
  if ((fp->_flags & __SRD) == 0)
  if ((fp->_flags & __SRD) == 0)
    {
    {
      /*
      /*
       * Not already reading: no good unless reading-and-writing.
       * Not already reading: no good unless reading-and-writing.
       * Otherwise, flush any current write stuff.
       * Otherwise, flush any current write stuff.
       */
       */
      if ((fp->_flags & __SRW) == 0)
      if ((fp->_flags & __SRW) == 0)
        {
        {
          _funlockfile (fp);
          _funlockfile (fp);
          return EOF;
          return EOF;
        }
        }
      if (fp->_flags & __SWR)
      if (fp->_flags & __SWR)
        {
        {
          if (_fflush_r (rptr, fp))
          if (_fflush_r (rptr, fp))
            {
            {
              _funlockfile (fp);
              _funlockfile (fp);
              return EOF;
              return EOF;
            }
            }
          fp->_flags &= ~__SWR;
          fp->_flags &= ~__SWR;
          fp->_w = 0;
          fp->_w = 0;
          fp->_lbfsize = 0;
          fp->_lbfsize = 0;
        }
        }
      fp->_flags |= __SRD;
      fp->_flags |= __SRD;
    }
    }
  c = (unsigned char) c;
  c = (unsigned char) c;
 
 
  /*
  /*
   * If we are in the middle of ungetc'ing, just continue.
   * If we are in the middle of ungetc'ing, just continue.
   * This may require expanding the current ungetc buffer.
   * This may require expanding the current ungetc buffer.
   */
   */
 
 
  if (HASUB (fp))
  if (HASUB (fp))
    {
    {
      if (fp->_r >= fp->_ub._size && __submore (rptr, fp))
      if (fp->_r >= fp->_ub._size && __submore (rptr, fp))
        {
        {
          _funlockfile (fp);
          _funlockfile (fp);
          return EOF;
          return EOF;
        }
        }
      *--fp->_p = c;
      *--fp->_p = c;
      fp->_r++;
      fp->_r++;
      _funlockfile (fp);
      _funlockfile (fp);
      return c;
      return c;
    }
    }
 
 
  /*
  /*
   * If we can handle this by simply backing up, do so,
   * If we can handle this by simply backing up, do so,
   * but never replace the original character.
   * but never replace the original character.
   * (This makes sscanf() work when scanning `const' data.)
   * (This makes sscanf() work when scanning `const' data.)
   */
   */
 
 
  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
    {
    {
      fp->_p--;
      fp->_p--;
      fp->_r++;
      fp->_r++;
      _funlockfile (fp);
      _funlockfile (fp);
      return c;
      return c;
    }
    }
 
 
  /*
  /*
   * Create an ungetc buffer.
   * Create an ungetc buffer.
   * Initially, we will use the `reserve' buffer.
   * Initially, we will use the `reserve' buffer.
   */
   */
 
 
  fp->_ur = fp->_r;
  fp->_ur = fp->_r;
  fp->_up = fp->_p;
  fp->_up = fp->_p;
  fp->_ub._base = fp->_ubuf;
  fp->_ub._base = fp->_ubuf;
  fp->_ub._size = sizeof (fp->_ubuf);
  fp->_ub._size = sizeof (fp->_ubuf);
  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
  fp->_r = 1;
  fp->_r = 1;
  _funlockfile (fp);
  _funlockfile (fp);
  return c;
  return c;
}
}
 
 
#ifndef _REENT_ONLY
#ifndef _REENT_ONLY
int
int
_DEFUN(ungetc, (c, fp),
_DEFUN(ungetc, (c, fp),
       int c               _AND
       int c               _AND
       register FILE *fp)
       register FILE *fp)
{
{
  return _ungetc_r (_REENT, c, fp);
  return _ungetc_r (_REENT, c, fp);
}
}
#endif /* !_REENT_ONLY */
#endif /* !_REENT_ONLY */
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.