1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
/***
*ungetc.c - unget a character from a stream
*
* Copyright (c) 1985-1993, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines ungetc() - pushes a character back onto an input stream
*
*Revision History:
* 09-02-83 RN initial version
* 04-16-87 JCR added support for _IOUNGETC flag
* 08-04-87 JCR (1) Added _IOSTRG check before setting _IOUNGETC flag.
* (2) Allow an ugnetc() before a read has occurred (get a
* buffer (ANSI). [MSC only]
* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
* 11-04-87 JCR Multi-thread support
* 12-11-87 JCR Added "_LOAD_DS" to declaration
* 05-25-88 JCR Allow an ungetc() before read for file opened "r+".
* 05-31-88 PHG Merged DLL and normal versions
* 06-06-88 JCR Optimized _iob2 references
* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
* 08-25-88 GJF Don't use FP_OFF() macro for the 386
* 04-11-89 JCR Removed _IOUNGETC flag, fseek() no longer needs it
* 08-17-89 GJF Clean up, now specific to OS/2 2.0 (i.e., 386 flat
* model). Also fixed copyright and indents.
* 02-16-90 GJF Fixed copyright
* 03-20-90 GJF Made calling type _CALLTYPE1, added #include
* <cruntime.h> and removed #include <register.h>.
* 07-23-90 SBM Replaced <assertm.h> by <assert.h>
* 08-13-90 SBM Compiles cleanly with -W3
* 10-03-90 GJF New-style function declarators.
* 11-07-92 SRW Dont modify buffer if stream opened by sscanf
* 04-26-93 CFW Wide char enable.
* 04-30-93 CFW Remove wide char support to ungetwc.c.
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <assert.h>
#include <internal.h>
#include <os2dll.h>
#ifdef MTHREAD /* multi-thread; define both ungetc and _lk_ungetc */
/***
*int ungetc(ch, stream) - put a character back onto a stream
*
*Purpose:
* Guaranteed one char pushback on a stream as long as open for reading.
* More than one char pushback in a row is not guaranteed, and will fail
* if it follows an ungetc which pushed the first char in buffer. Failure
* causes return of EOF.
*
*Entry:
* char ch - character to push back
* FILE *stream - stream to push character onto
*
*Exit:
* returns ch
* returns EOF if tried to push EOF, stream not opened for reading or
* or if we have already ungetc'd back to beginning of buffer.
*
*Exceptions:
*
*******************************************************************************/
int _CRTAPI1 ungetc (
REG2 int ch,
REG1 FILE *stream
)
{
int retval;
int index;
assert(stream != NULL);
index = _iob_index(stream);
_lock_str(index);
retval = _ungetc_lk (ch, stream);
_unlock_str(index);
return(retval);
}
/***
*_ungetc_lk() - Ungetc() core routine (locked version)
*
*Purpose:
* Core ungetc() routine; assumes stream is already locked.
*
* [See ungetc() above for more info.]
*
*Entry: [See ungetc()]
*
*Exit: [See ungetc()]
*
*Exceptions:
*
*******************************************************************************/
int _CRTAPI1 _ungetc_lk (
REG2 int ch,
FILE *str
)
{
#else /* non multi-thread; just define ungetc */
int _CRTAPI1 ungetc (
REG2 int ch,
FILE *str
)
{
#endif /* rejoin common code */
REG1 FILE *stream;
assert(str != NULL);
/* Init stream pointer and file descriptor */
stream = str;
/* Stream must be open for read and can NOT be currently in write mode.
Also, ungetc() character cannot be EOF. */
if (
(ch == EOF) ||
!(
(stream->_flag & _IOREAD) ||
((stream->_flag & _IORW) && !(stream->_flag & _IOWRT))
)
)
return(EOF);
/* If stream is unbuffered, get one. */
if (stream->_base == NULL)
_getbuf(stream);
/* now we know _base != NULL; since file must be buffered */
if (stream->_ptr == stream->_base) {
if (stream->_cnt)
/* my back is against the wall; i've already done
* ungetc, and there's no room for this one
*/
return(EOF);
stream->_ptr++;
}
if (stream->_flag & _IOSTRG) {
/* If stream opened by sscanf do not modify buffer */
if (*--stream->_ptr != (char)ch) {
++stream->_ptr;
return(EOF);
}
} else
*--stream->_ptr = (char)ch;
stream->_cnt++;
stream->_flag &= ~_IOEOF;
stream->_flag |= _IOREAD; /* may already be set */
return(0xff & ch);
}
|