ungetc.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       ungetc.c (4503B)
       ---
            1 /*-
            2  * Copyright (c) 1990, 1993
            3  *        The Regents of the University of California.  All rights reserved.
            4  *
            5  * This code is derived from software contributed to Berkeley by
            6  * Chris Torek.
            7  *
            8  * Redistribution and use in source and binary forms, with or without
            9  * modification, are permitted provided that the following conditions
           10  * are met:
           11  * 1. Redistributions of source code must retain the above copyright
           12  *    notice, this list of conditions and the following disclaimer.
           13  * 2. Redistributions in binary form must reproduce the above copyright
           14  *    notice, this list of conditions and the following disclaimer in the
           15  *    documentation and/or other materials provided with the distribution.
           16  * 3. All advertising materials mentioning features or use of this software
           17  *    must display the following acknowledgement:
           18  *        This product includes software developed by the University of
           19  *        California, Berkeley and its contributors.
           20  * 4. Neither the name of the University nor the names of its contributors
           21  *    may be used to endorse or promote products derived from this software
           22  *    without specific prior written permission.
           23  *
           24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
           25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
           26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
           27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
           28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
           29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
           30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
           31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
           32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
           33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
           34  * SUCH DAMAGE.
           35  */
           36 
           37 #if defined(LIBC_SCCS) && !defined(lint)
           38 static char rcsid[] = "$OpenBSD: ungetc.c,v 1.2 1996/08/19 08:33:11 tholo Exp $";
           39 #endif /* LIBC_SCCS and not lint */
           40 
           41 #include <stdio.h>
           42 #include <stdlib.h>
           43 #include <string.h>
           44 #include "local.h"
           45 
           46 /*
           47  * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
           48  * the buffer moves, so that it points the same distance from the end,
           49  * and move the bytes in the buffer around as necessary so that they
           50  * are all at the end (stack-style).
           51  */
           52 static int
           53 __submore(fp)
           54         register FILE *fp;
           55 {
           56         register int i;
           57         register unsigned char *p;
           58 
           59         if (fp->_ub._base == fp->_ubuf) {
           60                 /*
           61                  * Get a new buffer (rather than expanding the old one).
           62                  */
           63                 if ((p = malloc((size_t)BUFSIZ)) == NULL)
           64                         return (EOF);
           65                 fp->_ub._base = p;
           66                 fp->_ub._size = BUFSIZ;
           67                 p += BUFSIZ - sizeof(fp->_ubuf);
           68                 for (i = sizeof(fp->_ubuf); --i >= 0;)
           69                         p[i] = fp->_ubuf[i];
           70                 fp->_p = p;
           71                 return (0);
           72         }
           73         i = fp->_ub._size;
           74         p = realloc(fp->_ub._base, i << 1);
           75         if (p == NULL)
           76                 return (EOF);
           77         /* no overlap (hence can use memcpy) because we doubled the size */
           78         (void)memcpy((void *)(p + i), (void *)p, (size_t)i);
           79         fp->_p = p + i;
           80         fp->_ub._base = p;
           81         fp->_ub._size = i << 1;
           82         return (0);
           83 }
           84 
           85 int
           86 ungetc(c, fp)
           87         int c;
           88         register FILE *fp;
           89 {
           90         if (c == EOF)
           91                 return (EOF);
           92         if (!__sdidinit)
           93                 __sinit();
           94         if ((fp->_flags & __SRD) == 0) {
           95                 /*
           96                  * Not already reading: no good unless reading-and-writing.
           97                  * Otherwise, flush any current write stuff.
           98                  */
           99                 if ((fp->_flags & __SRW) == 0)
          100                         return (EOF);
          101                 if (fp->_flags & __SWR) {
          102                         if (__sflush(fp))
          103                                 return (EOF);
          104                         fp->_flags &= ~__SWR;
          105                         fp->_w = 0;
          106                         fp->_lbfsize = 0;
          107                 }
          108                 fp->_flags |= __SRD;
          109         }
          110         c = (unsigned char)c;
          111 
          112         /*
          113          * If we are in the middle of ungetc'ing, just continue.
          114          * This may require expanding the current ungetc buffer.
          115          */
          116         if (HASUB(fp)) {
          117                 if (fp->_r >= fp->_ub._size && __submore(fp))
          118                         return (EOF);
          119                 *--fp->_p = c;
          120                 fp->_r++;
          121                 return (c);
          122         }
          123         fp->_flags &= ~__SEOF;
          124 
          125         /*
          126          * If we can handle this by simply backing up, do so,
          127          * but never replace the original character.
          128          * (This makes sscanf() work when scanning `const' data.)
          129          */
          130         if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
          131             fp->_p[-1] == c) {
          132                 fp->_p--;
          133                 fp->_r++;
          134                 return (c);
          135         }
          136 
          137         /*
          138          * Create an ungetc buffer.
          139          * Initially, we will use the `reserve' buffer.
          140          */
          141         fp->_ur = fp->_r;
          142         fp->_up = fp->_p;
          143         fp->_ub._base = fp->_ubuf;
          144         fp->_ub._size = sizeof(fp->_ubuf);
          145         fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
          146         fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
          147         fp->_r = 1;
          148         return (c);
          149 }