~xnox/ubuntu/trusty/gcc-arm-linux-androideabi/dima

« back to all changes in this revision

Viewing changes to android/bionic/libc/stdio/ungetc.c

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-07-05 10:12:24 UTC
  • Revision ID: package-import@ubuntu.com-20130705101224-6qo3e8jbz8p31aa1
Tags: upstream-0.20130705.1
ImportĀ upstreamĀ versionĀ 0.20130705.1

Show diffs side-by-side

added added

removed removed

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