Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4874 Rev 4921
1
/*
1
/*
2
 * Copyright (c) 1990 The Regents of the University of California.
2
 * Copyright (c) 1990 The Regents of the University of California.
3
 * All rights reserved.
3
 * All rights reserved.
4
 *
4
 *
5
 * Redistribution and use in source and binary forms are permitted
5
 * Redistribution and use in source and binary forms are permitted
6
 * provided that the above copyright notice and this paragraph are
6
 * provided that the above copyright notice and this paragraph are
7
 * duplicated in all such forms and that any documentation,
7
 * duplicated in all such forms and that any documentation,
8
 * advertising materials, and other materials related to such
8
 * advertising materials, and other materials related to such
9
 * distribution and use acknowledge that the software was developed
9
 * distribution and use acknowledge that the software was developed
10
 * by the University of California, Berkeley.  The name of the
10
 * by the University of California, Berkeley.  The name of the
11
 * University may not be used to endorse or promote products derived
11
 * University may not be used to endorse or promote products derived
12
 * from this software without specific prior written permission.
12
 * from this software without specific prior written permission.
13
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
15
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16
 */
16
 */
17
/*
17
/*
18
FUNCTION
18
FUNCTION
19
<>---push data back into a stream
19
<>---push data back into a stream
20
 
20
 
21
INDEX
21
INDEX
22
	ungetc
22
	ungetc
23
INDEX
23
INDEX
24
	_ungetc_r
24
	_ungetc_r
25
 
25
 
26
ANSI_SYNOPSIS
26
ANSI_SYNOPSIS
27
	#include 
27
	#include 
28
	int ungetc(int <[c]>, FILE *<[stream]>);
28
	int ungetc(int <[c]>, FILE *<[stream]>);
29
 
29
 
30
	int _ungetc_r(struct _reent *<[reent]>, int <[c]>, FILE *<[stream]>);
30
	int _ungetc_r(struct _reent *<[reent]>, int <[c]>, FILE *<[stream]>);
31
 
31
 
32
DESCRIPTION
32
DESCRIPTION
33
<> is used to return bytes back to <[stream]> to be read again.
33
<> is used to return bytes back to <[stream]> to be read again.
34
If <[c]> is EOF, the stream is unchanged.  Otherwise, the unsigned
34
If <[c]> is EOF, the stream is unchanged.  Otherwise, the unsigned
35
char <[c]> is put back on the stream, and subsequent reads will see
35
char <[c]> is put back on the stream, and subsequent reads will see
36
the bytes pushed back in reverse order.  Pushed byes are lost if the
36
the bytes pushed back in reverse order.  Pushed byes are lost if the
37
stream is repositioned, such as by <>, <>, or
37
stream is repositioned, such as by <>, <>, or
38
<>.
38
<>.
39
 
39
 
40
The underlying file is not changed, but it is possible to push back
40
The underlying file is not changed, but it is possible to push back
41
something different than what was originally read.  Ungetting a
41
something different than what was originally read.  Ungetting a
42
character will clear the end-of-stream marker, and decrement the file
42
character will clear the end-of-stream marker, and decrement the file
43
position indicator.  Pushing back beyond the beginning of a file gives
43
position indicator.  Pushing back beyond the beginning of a file gives
44
unspecified behavior.
44
unspecified behavior.
45
 
45
 
46
The alternate function <<_ungetc_r>> is a reentrant version.  The
46
The alternate function <<_ungetc_r>> is a reentrant version.  The
47
extra argument <[reent]> is a pointer to a reentrancy structure.
47
extra argument <[reent]> is a pointer to a reentrancy structure.
48
 
48
 
49
RETURNS
49
RETURNS
50
The character pushed back, or <> on error.
50
The character pushed back, or <> on error.
51
 
51
 
52
PORTABILITY
52
PORTABILITY
53
ANSI C requires <>, but only requires a pushback buffer of one
53
ANSI C requires <>, but only requires a pushback buffer of one
54
byte; although this implementation can handle multiple bytes, not all
54
byte; although this implementation can handle multiple bytes, not all
55
can.  Pushing back a signed char is a common application bug.
55
can.  Pushing back a signed char is a common application bug.
56
 
56
 
57
Supporting OS subroutines required: <>.
57
Supporting OS subroutines required: <>.
58
*/
58
*/
59
 
59
 
60
#if defined(LIBC_SCCS) && !defined(lint)
60
#if defined(LIBC_SCCS) && !defined(lint)
61
static char sccsid[] = "%W% (Berkeley) %G%";
61
static char sccsid[] = "%W% (Berkeley) %G%";
62
#endif /* LIBC_SCCS and not lint */
62
#endif /* LIBC_SCCS and not lint */
63
 
63
 
64
#include <_ansi.h>
64
#include <_ansi.h>
65
#include 
65
#include 
66
#include 
66
#include 
67
#include 
67
#include 
68
#include 
68
#include 
69
#include "local.h"
69
#include "local.h"
70
 
70
 
71
/*
71
/*
72
 * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
72
 * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
73
 * the buffer moves, so that it points the same distance from the end,
73
 * the buffer moves, so that it points the same distance from the end,
74
 * and move the bytes in the buffer around as necessary so that they
74
 * and move the bytes in the buffer around as necessary so that they
75
 * are all at the end (stack-style).
75
 * are all at the end (stack-style).
76
 */
76
 */
77
 
77
 
78
/*static*/
78
/*static*/
79
int
79
int
80
_DEFUN(__submore, (rptr, fp),
80
_DEFUN(__submore, (rptr, fp),
81
       struct _reent *rptr _AND
81
       struct _reent *rptr _AND
82
       register FILE *fp)
82
       register FILE *fp)
83
{
83
{
84
  register int i;
84
  register int i;
85
  register unsigned char *p;
85
  register unsigned char *p;
86
 
86
 
87
  if (fp->_ub._base == fp->_ubuf)
87
  if (fp->_ub._base == fp->_ubuf)
88
    {
88
    {
89
      /*
89
      /*
90
       * Get a new buffer (rather than expanding the old one).
90
       * Get a new buffer (rather than expanding the old one).
91
       */
91
       */
92
      if ((p = (unsigned char *) _malloc_r (rptr, (size_t) BUFSIZ)) == NULL)
92
      if ((p = (unsigned char *) _malloc_r (rptr, (size_t) BUFSIZ)) == NULL)
93
	return EOF;
93
	return EOF;
94
      fp->_ub._base = p;
94
      fp->_ub._base = p;
95
      fp->_ub._size = BUFSIZ;
95
      fp->_ub._size = BUFSIZ;
96
      p += BUFSIZ - sizeof (fp->_ubuf);
96
      p += BUFSIZ - sizeof (fp->_ubuf);
97
      for (i = sizeof (fp->_ubuf); --i >= 0;)
97
      for (i = sizeof (fp->_ubuf); --i >= 0;)
98
	p[i] = fp->_ubuf[i];
98
	p[i] = fp->_ubuf[i];
99
      fp->_p = p;
99
      fp->_p = p;
100
      return 0;
100
      return 0;
101
    }
101
    }
102
  i = fp->_ub._size;
102
  i = fp->_ub._size;
103
  p = (unsigned char *) _realloc_r (rptr, (_PTR) (fp->_ub._base), i << 1);
103
  p = (unsigned char *) _realloc_r (rptr, (_PTR) (fp->_ub._base), i << 1);
104
  if (p == NULL)
104
  if (p == NULL)
105
    return EOF;
105
    return EOF;
106
  _CAST_VOID memcpy ((_PTR) (p + i), (_PTR) p, (size_t) i);
106
  _CAST_VOID memcpy ((_PTR) (p + i), (_PTR) p, (size_t) i);
107
  fp->_p = p + i;
107
  fp->_p = p + i;
108
  fp->_ub._base = p;
108
  fp->_ub._base = p;
109
  fp->_ub._size = i << 1;
109
  fp->_ub._size = i << 1;
110
  return 0;
110
  return 0;
111
}
111
}
112
 
112
 
113
int
113
int
114
_DEFUN(_ungetc_r, (rptr, c, fp),
114
_DEFUN(_ungetc_r, (rptr, c, fp),
115
       struct _reent *rptr _AND
115
       struct _reent *rptr _AND
116
       int c               _AND
116
       int c               _AND
117
       register FILE *fp)
117
       register FILE *fp)
118
{
118
{
119
  if (c == EOF)
119
  if (c == EOF)
120
    return (EOF);
120
    return (EOF);
121
 
121
 
122
  /* Ensure stdio has been initialized.
122
  /* Ensure stdio has been initialized.
123
     ??? Might be able to remove this as some other stdio routine should
123
     ??? Might be able to remove this as some other stdio routine should
124
     have already been called to get the char we are un-getting.  */
124
     have already been called to get the char we are un-getting.  */
125
 
125
 
126
  CHECK_INIT (rptr, fp);
126
  CHECK_INIT (rptr, fp);
127
 
127
 
128
  _flockfile (fp);
128
  _newlib_flockfile_start (fp);
129
 
129
 
130
  ORIENT (fp, -1);
130
  ORIENT (fp, -1);
131
 
131
 
132
  /* After ungetc, we won't be at eof anymore */
132
  /* After ungetc, we won't be at eof anymore */
133
  fp->_flags &= ~__SEOF;
133
  fp->_flags &= ~__SEOF;
134
 
134
 
135
  if ((fp->_flags & __SRD) == 0)
135
  if ((fp->_flags & __SRD) == 0)
136
    {
136
    {
137
      /*
137
      /*
138
       * Not already reading: no good unless reading-and-writing.
138
       * Not already reading: no good unless reading-and-writing.
139
       * Otherwise, flush any current write stuff.
139
       * Otherwise, flush any current write stuff.
140
       */
140
       */
141
      if ((fp->_flags & __SRW) == 0)
141
      if ((fp->_flags & __SRW) == 0)
142
        {
142
        {
143
          _funlockfile (fp);
143
          _newlib_flockfile_exit (fp);
144
          return EOF;
144
          return EOF;
145
        }
145
        }
146
      if (fp->_flags & __SWR)
146
      if (fp->_flags & __SWR)
147
	{
147
	{
148
	  if (_fflush_r (rptr, fp))
148
	  if (_fflush_r (rptr, fp))
149
            {
149
            {
150
              _funlockfile (fp);
150
              _newlib_flockfile_exit (fp);
151
              return EOF;
151
              return EOF;
152
            }
152
            }
153
	  fp->_flags &= ~__SWR;
153
	  fp->_flags &= ~__SWR;
154
	  fp->_w = 0;
154
	  fp->_w = 0;
155
	  fp->_lbfsize = 0;
155
	  fp->_lbfsize = 0;
156
	}
156
	}
157
      fp->_flags |= __SRD;
157
      fp->_flags |= __SRD;
158
    }
158
    }
159
  c = (unsigned char) c;
159
  c = (unsigned char) c;
160
 
160
 
161
  /*
161
  /*
162
   * If we are in the middle of ungetc'ing, just continue.
162
   * If we are in the middle of ungetc'ing, just continue.
163
   * This may require expanding the current ungetc buffer.
163
   * This may require expanding the current ungetc buffer.
164
   */
164
   */
165
 
165
 
166
  if (HASUB (fp))
166
  if (HASUB (fp))
167
    {
167
    {
168
      if (fp->_r >= fp->_ub._size && __submore (rptr, fp))
168
      if (fp->_r >= fp->_ub._size && __submore (rptr, fp))
169
        {
169
        {
170
          _funlockfile (fp);
170
          _newlib_flockfile_exit (fp);
171
          return EOF;
171
          return EOF;
172
        }
172
        }
173
      *--fp->_p = c;
173
      *--fp->_p = c;
174
      fp->_r++;
174
      fp->_r++;
175
      _funlockfile (fp);
175
      _newlib_flockfile_exit (fp);
176
      return c;
176
      return c;
177
    }
177
    }
178
 
178
 
179
  /*
179
  /*
180
   * If we can handle this by simply backing up, do so,
180
   * If we can handle this by simply backing up, do so,
181
   * but never replace the original character.
181
   * but never replace the original character.
182
   * (This makes sscanf() work when scanning `const' data.)
182
   * (This makes sscanf() work when scanning `const' data.)
183
   */
183
   */
184
 
184
 
185
  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
185
  if (fp->_bf._base != NULL && fp->_p > fp->_bf._base && fp->_p[-1] == c)
186
    {
186
    {
187
      fp->_p--;
187
      fp->_p--;
188
      fp->_r++;
188
      fp->_r++;
189
      _funlockfile (fp);
189
      _newlib_flockfile_exit (fp);
190
      return c;
190
      return c;
191
    }
191
    }
192
 
192
 
193
  /*
193
  /*
194
   * Create an ungetc buffer.
194
   * Create an ungetc buffer.
195
   * Initially, we will use the `reserve' buffer.
195
   * Initially, we will use the `reserve' buffer.
196
   */
196
   */
197
 
197
 
198
  fp->_ur = fp->_r;
198
  fp->_ur = fp->_r;
199
  fp->_up = fp->_p;
199
  fp->_up = fp->_p;
200
  fp->_ub._base = fp->_ubuf;
200
  fp->_ub._base = fp->_ubuf;
201
  fp->_ub._size = sizeof (fp->_ubuf);
201
  fp->_ub._size = sizeof (fp->_ubuf);
202
  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
202
  fp->_ubuf[sizeof (fp->_ubuf) - 1] = c;
203
  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
203
  fp->_p = &fp->_ubuf[sizeof (fp->_ubuf) - 1];
204
  fp->_r = 1;
204
  fp->_r = 1;
205
  _funlockfile (fp);
205
  _newlib_flockfile_end (fp);
206
  return c;
206
  return c;
207
}
207
}
208
 
208
 
209
#ifndef _REENT_ONLY
209
#ifndef _REENT_ONLY
210
int
210
int
211
_DEFUN(ungetc, (c, fp),
211
_DEFUN(ungetc, (c, fp),
212
       int c               _AND
212
       int c               _AND
213
       register FILE *fp)
213
       register FILE *fp)
214
{
214
{
215
  return _ungetc_r (_REENT, c, fp);
215
  return _ungetc_r (_REENT, c, fp);
216
}
216
}
217
#endif /* !_REENT_ONLY */
217
#endif /* !_REENT_ONLY */