fixes for host gcc 4.6.1
[zpugcc/jano.git] / toolchain / gcc / newlib / libc / stdio / ungetc.c
blob5ca98251d56e39bf87baca2fbc75c646cdf555fe
1 /*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
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.
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "%W% (Berkeley) %G%";
20 #endif /* LIBC_SCCS and not lint */
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include "local.h"
28 * Expand the ungetc buffer `in place'. That is, adjust fp->_p when
29 * the buffer moves, so that it points the same distance from the end,
30 * and move the bytes in the buffer around as necessary so that they
31 * are all at the end (stack-style).
34 /*static*/
35 int
36 __submore (fp)
37 register FILE *fp;
39 register int i;
40 register unsigned char *p;
42 if (fp->_ub._base == fp->_ubuf)
45 * Get a new buffer (rather than expanding the old one).
47 if ((p = (unsigned char *) _malloc_r (_REENT, (size_t) BUFSIZ)) == NULL)
48 return EOF;
49 fp->_ub._base = p;
50 fp->_ub._size = BUFSIZ;
51 p += BUFSIZ - sizeof (fp->_ubuf);
52 for (i = sizeof (fp->_ubuf); --i >= 0;)
53 p[i] = fp->_ubuf[i];
54 fp->_p = p;
55 return 0;
57 i = fp->_ub._size;
58 p = (unsigned char *) _realloc_r (_REENT, (_PTR) (fp->_ub._base), i << 1);
59 if (p == NULL)
60 return EOF;
61 (void) memcpy ((void *) (p + i), (void *) p, (size_t) i);
62 fp->_p = p + i;
63 fp->_ub._base = p;
64 fp->_ub._size = i << 1;
65 return 0;
68 int
69 ungetc (c, fp)
70 int c;
71 register FILE *fp;
73 if (c == EOF)
74 return (EOF);
76 _flockfile(fp);
78 /* Ensure stdio has been initialized.
79 ??? Might be able to remove this as some other stdio routine should
80 have already been called to get the char we are un-getting. */
82 CHECK_INIT (fp);
84 /* After ungetc, we won't be at eof anymore */
85 fp->_flags &= ~__SEOF;
87 if ((fp->_flags & __SRD) == 0)
90 * Not already reading: no good unless reading-and-writing.
91 * Otherwise, flush any current write stuff.
93 if ((fp->_flags & __SRW) == 0)
95 _funlockfile(fp);
96 return EOF;
98 if (fp->_flags & __SWR)
100 if (fflush (fp))
102 _funlockfile(fp);
103 return EOF;
105 fp->_flags &= ~__SWR;
106 fp->_w = 0;
107 fp->_lbfsize = 0;
109 fp->_flags |= __SRD;
111 c = (unsigned char) c;
114 * If we are in the middle of ungetc'ing, just continue.
115 * This may require expanding the current ungetc buffer.
118 if (HASUB (fp))
120 if (fp->_r >= fp->_ub._size && __submore (fp))
122 _funlockfile(fp);
123 return EOF;
125 *--fp->_p = c;
126 fp->_r++;
127 _funlockfile(fp);
128 return c;
132 * If we can handle this by simply backing up, do so,
133 * but never replace the original character.
134 * (This makes sscanf() work when scanning `const' data.)
137 if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
139 fp->_p--;
140 fp->_r++;
141 _funlockfile(fp);
142 return c;
146 * Create an ungetc buffer.
147 * Initially, we will use the `reserve' buffer.
150 fp->_ur = fp->_r;
151 fp->_up = fp->_p;
152 fp->_ub._base = fp->_ubuf;
153 fp->_ub._size = sizeof (fp->_ubuf);
154 fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
155 fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
156 fp->_r = 1;
157 _funlockfile(fp);
158 return c;