sl@0: /* UNGETC.C sl@0: * sl@0: * Portions Copyright (c) 1990-1999 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: */ sl@0: sl@0: /* sl@0: * Copyright (c) 1990 The Regents of the University of California. sl@0: * All rights reserved. sl@0: * sl@0: * Redistribution and use in source and binary forms are permitted sl@0: * provided that the above copyright notice and this paragraph are sl@0: * duplicated in all such forms and that any documentation, sl@0: * advertising materials, and other materials related to such sl@0: * distribution and use acknowledge that the software was developed sl@0: * by the University of California, Berkeley. The name of the sl@0: * University may not be used to endorse or promote products derived sl@0: * from this software without specific prior written permission. sl@0: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR sl@0: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED sl@0: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. sl@0: */ sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include "LOCAL.H" sl@0: sl@0: /* sl@0: * Expand the ungetc buffer `in place'. That is, adjust fp->_p when sl@0: * the buffer moves, so that it points the same distance from the end, sl@0: * and move the bytes in the buffer around as necessary so that they sl@0: * are all at the end (stack-style). sl@0: */ sl@0: sl@0: /*static*/ sl@0: int sl@0: __submore (register FILE *fp) sl@0: { sl@0: register int i; sl@0: register unsigned char *p; sl@0: sl@0: if (fp->_ub._base == fp->_ubuf) sl@0: { sl@0: /* sl@0: * Get a new buffer (rather than expanding the old one). sl@0: */ sl@0: if ((p = (unsigned char *) _malloc_r (fp->_data, (size_t) BUFSIZ)) == NULL) sl@0: return EOF; sl@0: fp->_ub._base = p; sl@0: fp->_ub._size = BUFSIZ; sl@0: p += BUFSIZ - sizeof (fp->_ubuf); sl@0: for (i = sizeof (fp->_ubuf); --i >= 0;) sl@0: p[i] = fp->_ubuf[i]; sl@0: fp->_p = p; sl@0: return 0; sl@0: } sl@0: i = fp->_ub._size; sl@0: p = (unsigned char *) _realloc_r (fp->_data, (void*) (fp->_ub._base), i << 1); sl@0: if (p == NULL) sl@0: return EOF; sl@0: (void) memcpy ((void *) (p + i), (void *) p, (size_t) i); sl@0: fp->_p = p + i; sl@0: fp->_ub._base = p; sl@0: fp->_ub._size = i << 1; sl@0: return 0; sl@0: } sl@0: sl@0: /** sl@0: Push a character back into stream. sl@0: @return If successful, the character putted is returned. sl@0: Otherwise EOF is returned and the stream remains unchanged. sl@0: @param c character to be pushed. sl@0: @param fp pointer to an open file. sl@0: */ sl@0: EXPORT_C int sl@0: ungetc (int c,register FILE *fp) sl@0: { sl@0: if (c == EOF) sl@0: return (EOF); sl@0: sl@0: /* Ensure stdio has been initialized. sl@0: ??? Might be able to remove this as some other stdio routine should sl@0: have already been called to get the char we are un-getting. */ sl@0: sl@0: CHECK_INIT (fp); sl@0: sl@0: /* After ungetc, we won't be at eof anymore */ sl@0: fp->_flags &= ~__SEOF; sl@0: sl@0: if ((fp->_flags & __SRD) == 0) sl@0: { sl@0: /* sl@0: * Not already reading: no good unless reading-and-writing. sl@0: * Otherwise, flush any current write stuff. sl@0: */ sl@0: if ((fp->_flags & __SRW) == 0) sl@0: return EOF; sl@0: if (fp->_flags & __SWR) sl@0: { sl@0: if (fflush (fp)) sl@0: return EOF; sl@0: fp->_flags &= ~__SWR; sl@0: fp->_w = 0; sl@0: fp->_lbfsize = 0; sl@0: } sl@0: fp->_flags |= __SRD; sl@0: } sl@0: c = (unsigned char) c; sl@0: sl@0: /* sl@0: * If we are in the middle of ungetc'ing, just continue. sl@0: * This may require expanding the current ungetc buffer. sl@0: */ sl@0: sl@0: if (HASUB (fp)) sl@0: { sl@0: if (fp->_r >= fp->_ub._size && __submore (fp)) sl@0: return EOF; sl@0: *--fp->_p = (unsigned char)c; sl@0: fp->_r++; sl@0: return c; sl@0: } sl@0: sl@0: /* sl@0: * If we can handle this by simply backing up, do so, sl@0: * but never replace the original character. sl@0: * (This makes sscanf() work when scanning `const' data.) sl@0: */ sl@0: sl@0: if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c) sl@0: { sl@0: fp->_p--; sl@0: fp->_r++; sl@0: return c; sl@0: } sl@0: sl@0: /* sl@0: * Create an ungetc buffer. sl@0: * Initially, we will use the `reserve' buffer. sl@0: */ sl@0: sl@0: fp->_ur = fp->_r; sl@0: fp->_up = fp->_p; sl@0: fp->_ub._base = fp->_ubuf; sl@0: fp->_ub._size = sizeof (fp->_ubuf); sl@0: fp->_ubuf[sizeof (fp->_ubuf) - 1] = (unsigned char)c; sl@0: fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1]; sl@0: fp->_r = 1; sl@0: return c; sl@0: }