source: trunk/libs/newlib/src/newlib/libc/stdio/ungetc.c @ 567

Last change on this file since 567 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17/*
18FUNCTION
19<<ungetc>>---push data back into a stream
20
21INDEX
22        ungetc
23INDEX
24        _ungetc_r
25
26SYNOPSIS
27        #include <stdio.h>
28        int ungetc(int <[c]>, FILE *<[stream]>);
29
30        int _ungetc_r(struct _reent *<[reent]>, int <[c]>, FILE *<[stream]>);
31
32DESCRIPTION
33<<ungetc>> is used to return bytes back to <[stream]> to be read again.
34If <[c]> is EOF, the stream is unchanged.  Otherwise, the unsigned
35char <[c]> is put back on the stream, and subsequent reads will see
36the bytes pushed back in reverse order.  Pushed byes are lost if the
37stream is repositioned, such as by <<fseek>>, <<fsetpos>>, or
38<<rewind>>.
39
40The underlying file is not changed, but it is possible to push back
41something different than what was originally read.  Ungetting a
42character will clear the end-of-stream marker, and decrement the file
43position indicator.  Pushing back beyond the beginning of a file gives
44unspecified behavior.
45
46The alternate function <<_ungetc_r>> is a reentrant version.  The
47extra argument <[reent]> is a pointer to a reentrancy structure.
48
49RETURNS
50The character pushed back, or <<EOF>> on error.
51
52PORTABILITY
53ANSI C requires <<ungetc>>, but only requires a pushback buffer of one
54byte; although this implementation can handle multiple bytes, not all
55can.  Pushing back a signed char is a common application bug.
56
57Supporting OS subroutines required: <<sbrk>>.
58*/
59
60#if defined(LIBC_SCCS) && !defined(lint)
61static char sccsid[] = "%W% (Berkeley) %G%";
62#endif /* LIBC_SCCS and not lint */
63
64#include <_ansi.h>
65#include <reent.h>
66#include <stdio.h>
67#include <stdlib.h>
68#include <string.h>
69#include "local.h"
70
71/*
72 * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
73 * the buffer moves, so that it points the same distance from the end,
74 * and move the bytes in the buffer around as necessary so that they
75 * are all at the end (stack-style).
76 */
77
78/*static*/
79int
80__submore (struct _reent *rptr,
81       register FILE *fp)
82{
83  register int i;
84  register unsigned char *p;
85
86  if (fp->_ub._base == fp->_ubuf)
87    {
88      /*
89       * Get a new buffer (rather than expanding the old one).
90       */
91      if ((p = (unsigned char *) _malloc_r (rptr, (size_t) BUFSIZ)) == NULL)
92        return EOF;
93      fp->_ub._base = p;
94      fp->_ub._size = BUFSIZ;
95      p += BUFSIZ - sizeof (fp->_ubuf);
96      for (i = sizeof (fp->_ubuf); --i >= 0;)
97        p[i] = fp->_ubuf[i];
98      fp->_p = p;
99      return 0;
100    }
101  i = fp->_ub._size;
102  p = (unsigned char *) _realloc_r (rptr, (void *) (fp->_ub._base), i << 1);
103  if (p == NULL)
104    return EOF;
105  (void) memcpy ((void *) (p + i), (void *) p, (size_t) i);
106  fp->_p = p + i;
107  fp->_ub._base = p;
108  fp->_ub._size = i << 1;
109  return 0;
110}
111
112int
113_ungetc_r (struct _reent *rptr,
114       int c,
115       register FILE *fp)
116{
117  if (c == EOF)
118    return (EOF);
119
120  /* Ensure stdio has been initialized.
121     ??? Might be able to remove this as some other stdio routine should
122     have already been called to get the char we are un-getting.  */
123
124  CHECK_INIT (rptr, fp);
125
126  _newlib_flockfile_start (fp);
127
128  ORIENT (fp, -1);
129
130  /* After ungetc, we won't be at eof anymore */
131  fp->_flags &= ~__SEOF;
132
133  if ((fp->_flags & __SRD) == 0)
134    {
135      /*
136       * Not already reading: no good unless reading-and-writing.
137       * Otherwise, flush any current write stuff.
138       */
139      if ((fp->_flags & __SRW) == 0)
140        {
141          _newlib_flockfile_exit (fp);
142          return EOF;
143        }
144      if (fp->_flags & __SWR)
145        {
146          if (_fflush_r (rptr, fp))
147            {
148              _newlib_flockfile_exit (fp);
149              return EOF;
150            }
151          fp->_flags &= ~__SWR;
152          fp->_w = 0;
153          fp->_lbfsize = 0;
154        }
155      fp->_flags |= __SRD;
156    }
157  c = (unsigned char) c;
158
159  /*
160   * If we are in the middle of ungetc'ing, just continue.
161   * This may require expanding the current ungetc buffer.
162   */
163
164  if (HASUB (fp))
165    {
166      if (fp->_r >= fp->_ub._size && __submore (rptr, fp))
167        {
168          _newlib_flockfile_exit (fp);
169          return EOF;
170        }
171      *--fp->_p = c;
172      fp->_r++;
173      _newlib_flockfile_exit (fp);
174      return c;
175    }
176
177  /*
178   * If we can handle this by simply backing up, do so,
179   * but never replace the original character.
180   * (This makes sscanf() work when scanning `const' data.)
181   */
182
183  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
184    {
185      fp->_p--;
186      fp->_r++;
187      _newlib_flockfile_exit (fp);
188      return c;
189    }
190
191  /*
192   * Create an ungetc buffer.
193   * Initially, we will use the `reserve' buffer.
194   */
195
196  fp->_ur = fp->_r;
197  fp->_up = fp->_p;
198  fp->_ub._base = fp->_ubuf;
199  fp->_ub._size = sizeof (fp->_ubuf);
200  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
201  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
202  fp->_r = 1;
203  _newlib_flockfile_end (fp);
204  return c;
205}
206
207#ifndef _REENT_ONLY
208int
209ungetc (int c,
210       register FILE *fp)
211{
212  return _ungetc_r (_REENT, c, fp);
213}
214#endif /* !_REENT_ONLY */
Note: See TracBrowser for help on using the repository browser.