gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/stdio/ungetc.cbare sourcepermlink (0.02 seconds)

Search this content:

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