146108Sbostic /*- 246108Sbostic * Copyright (c) 1990 The Regents of the University of California. 346108Sbostic * All rights reserved. 446108Sbostic * 546108Sbostic * This code is derived from software contributed to Berkeley by 646108Sbostic * Chris Torek. 746108Sbostic * 846108Sbostic * %sccs.include.redist.c% 946108Sbostic */ 1046108Sbostic 1126665Sdonn #if defined(LIBC_SCCS) && !defined(lint) 12*46219Sbostic static char sccsid[] = "@(#)ungetc.c 5.5 (Berkeley) 02/01/91"; 1346108Sbostic #endif /* LIBC_SCCS and not lint */ 1415084Ssam 152037Swnj #include <stdio.h> 1646108Sbostic #include <stdlib.h> 1746108Sbostic #include <string.h> 1846108Sbostic #include "local.h" 192037Swnj 2046108Sbostic /* 2146108Sbostic * Expand the ungetc buffer `in place'. That is, adjust fp->_p when 2246108Sbostic * the buffer moves, so that it points the same distance from the end, 2346108Sbostic * and move the bytes in the buffer around as necessary so that they 2446108Sbostic * are all at the end (stack-style). 2546108Sbostic */ 2646108Sbostic static 2746108Sbostic __submore(fp) 2846108Sbostic register FILE *fp; 292037Swnj { 3046108Sbostic register int i; 3146108Sbostic register unsigned char *p; 3246108Sbostic 3346108Sbostic if (fp->_ub._base == fp->_ubuf) { 3446108Sbostic /* 3546108Sbostic * Get a new buffer (rather than expanding the old one). 3646108Sbostic */ 3746108Sbostic if ((p = malloc((size_t)BUFSIZ)) == NULL) 3846108Sbostic return (EOF); 3946108Sbostic fp->_ub._base = p; 4046108Sbostic fp->_ub._size = BUFSIZ; 4146108Sbostic p += BUFSIZ - sizeof(fp->_ubuf); 4246108Sbostic for (i = sizeof(fp->_ubuf); --i >= 0;) 4346108Sbostic p[i] = fp->_ubuf[i]; 4446108Sbostic fp->_p = p; 4546108Sbostic return (0); 4646108Sbostic } 4746108Sbostic i = fp->_ub._size; 4846108Sbostic p = realloc(fp->_ub._base, i << 1); 4946108Sbostic if (p == NULL) 5017951Sserge return (EOF); 5146108Sbostic (void) memcpy((void *)(p + i), (void *)p, (size_t)i); 5246108Sbostic fp->_p = p + i; 5346108Sbostic fp->_ub._base = p; 5446108Sbostic fp->_ub._size = i << 1; 5546108Sbostic return (0); 5646108Sbostic } 5717951Sserge 5846108Sbostic ungetc(c, fp) 5946108Sbostic int c; 6046108Sbostic register FILE *fp; 6146108Sbostic { 6246108Sbostic if (c == EOF) 6346108Sbostic return (EOF); 6446108Sbostic if (!__sdidinit) 6546108Sbostic __sinit(); 6646108Sbostic if ((fp->_flags & __SRD) == 0) { 6746108Sbostic /* 6846108Sbostic * Not already reading: no good unless reading-and-writing. 6946108Sbostic * Otherwise, flush any current write stuff. 7046108Sbostic */ 7146108Sbostic if ((fp->_flags & __SRW) == 0) 7226938Sbloom return (EOF); 7346108Sbostic if (fp->_flags & __SWR) { 74*46219Sbostic if (__sflush(fp)) 7546108Sbostic return (EOF); 7646108Sbostic fp->_flags &= ~__SWR; 7746108Sbostic fp->_w = 0; 7846108Sbostic fp->_lbfsize = 0; 7946108Sbostic } 8046108Sbostic fp->_flags |= __SRD; 8146108Sbostic } 8246108Sbostic c = (unsigned char)c; 8317951Sserge 8446108Sbostic /* 8546108Sbostic * If we are in the middle of ungetc'ing, just continue. 8646108Sbostic * This may require expanding the current ungetc buffer. 8746108Sbostic */ 8846108Sbostic if (HASUB(fp)) { 8946108Sbostic if (fp->_r >= fp->_ub._size && __submore(fp)) 9046108Sbostic return (EOF); 9146108Sbostic *--fp->_p = c; 9246108Sbostic fp->_r++; 9346108Sbostic return (c); 9446108Sbostic } 9517951Sserge 9646108Sbostic /* 9746108Sbostic * If we can handle this by simply backing up, do so, 9846108Sbostic * but never replace the original character. 9946108Sbostic * (This makes sscanf() work when scanning `const' data.) 10046108Sbostic */ 10146108Sbostic if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && 10246108Sbostic fp->_p[-1] == c) { 10346108Sbostic fp->_p--; 10446108Sbostic fp->_r++; 10546108Sbostic return (c); 10646108Sbostic } 10746108Sbostic 10846108Sbostic /* 10946108Sbostic * Create an ungetc buffer. 11046108Sbostic * Initially, we will use the `reserve' buffer. 11146108Sbostic */ 11246108Sbostic fp->_ur = fp->_r; 11346108Sbostic fp->_up = fp->_p; 11446108Sbostic fp->_ub._base = fp->_ubuf; 11546108Sbostic fp->_ub._size = sizeof(fp->_ubuf); 11646108Sbostic fp->_ubuf[sizeof(fp->_ubuf) - 1] = c; 11746108Sbostic fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1]; 11846108Sbostic fp->_r = 1; 11915084Ssam return (c); 1202037Swnj } 121