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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
|
/***
*ftell.c - get current file position
*
* Copyright (c) 1985-1992, Microsoft Corporation. All rights reserved.
*
*Purpose:
* defines ftell() - find current current position of file pointer
*
*Revision History:
* 09-02-83 RN initial version
* ??-??-?? TC added code to allow variable buffer sizes
* 05-22-86 TC added code to seek to send if last operation was a
* write and append mode specified
* 11-20-86 SKS do not seek to end of file in append mode
* 12-01-86 SKS fix off-by-1 problem in text mode when last byte in
* buffer was a '\r', and it was followed by a '\n'. Since
* the \n was pushed back and the \r was discarded, we
* must adjust the computed position for the \r.
* 02-09-87 JCR Added errno set code (if flag (_IORW not set)
* 09-09-87 JCR Optimized to eliminate two lseek() calls in binary mode.
* 09-28-87 JCR Corrected _iob2 indexing (now uses _iob_index() macro).
* 11-04-87 JCR Multi-thread version
* 12-11-87 JCR Added "_LOAD_DS" to declaration
* 01-13-88 JCR Removed unnecessary calls to mthread fileno/feof/ferror
* 05-27-88 PHG Merged DLL and normal versions
* 06-06-88 JCR Use _iob2_ macro instead of _iob_index
* 06-15-88 JCR Near reference to _iob[] entries; improve REG variables
* 07-27-88 JCR Changed some variables from int to unsigned (bug fix)
* 08-25-88 GJF Don't use FP_OFF() macro for the 386
* 12-05-88 JCR Added _IOCTRLZ support (fixes bug pertaining to ^Z at
* eof)
* 08-17-89 GJF Cleanup, now specific to OS/2 2.0 (i.e., 386 flat
* model), also fixed copyright
* 02-15-90 GJF _iob[], _iob2[] merge. Also, fixed copyright and
* indents.
* 03-19-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>
* 10-02-90 GJF New-style function declarators.
* 01-21-91 GJF ANSI naming.
* 03-27-92 DJM POSIX support.
* 08-26-92 GJF Include unistd.h for POSIX build.
* 09-01-92 GJF Fixed POSIX support (was returning -1 for all except
* read-write streams).
*
*******************************************************************************/
#include <cruntime.h>
#include <stdio.h>
#include <file2.h>
#include <assert.h>
#include <errno.h>
#ifdef _POSIX_
#include <unistd.h>
#else
#include <msdos.h>
#endif
#include <stddef.h>
#include <io.h>
#include <internal.h>
#ifndef _POSIX_
#include <os2dll.h>
#endif
/***
*long ftell(stream) - query stream file pointer
*
*Purpose:
* Find out what stream's position is. coordinate with buffering; adjust
* backward for read-ahead and forward for write-behind. This is NOT
* equivalent to fseek(stream,0L,1), because fseek will remove an ungetc,
* may flush buffers, etc.
*
*Entry:
* FILE *stream - stream to query for position
*
*Exit:
* return present file position if succeeds
* returns -1L and sets errno if fails
*
*Exceptions:
*
*******************************************************************************/
#ifdef MTHREAD /* multi-thread; define both ftell() and _lk_ftell() */
long _CALLTYPE1 ftell (
FILE *stream
)
{
long retval;
#ifdef MTHREAD
int index;
#endif
assert(stream != NULL);
#ifdef MTHREAD
index = _iob_index(stream);
#endif
_lock_str(index);
retval = _ftell_lk (stream);
_unlock_str(index);
return(retval);
}
/***
*_ftell_lk() - Ftell() core routine (assumes stream is locked).
*
*Purpose:
* Core ftell() routine; assumes caller has aquired stream lock).
*
* [See ftell() above for more info.]
*
*Entry: [See ftell()]
*
*Exit: [See ftell()]
*
*Exceptions:
*
*******************************************************************************/
long _CALLTYPE1 _ftell_lk (
#else /* non multi-thread; define only ftell() */
long _CALLTYPE1 ftell (
#endif /* rejoin common code */
FILE *str
)
{
REG1 FILE *stream;
unsigned int offset;
long filepos;
#ifndef _POSIX_
REG2 char *p;
char *max;
#endif
int fd;
unsigned int rdcnt;
assert(str != NULL);
/* Init stream pointer and file descriptor */
stream = str;
#ifdef _POSIX_
fd = fileno(stream);
#else
fd = _fileno(stream);
#endif
if (stream->_cnt < 0)
stream->_cnt = 0;
#ifdef _POSIX_
if ((filepos = lseek(fd, 0L, SEEK_CUR)) < 0L)
#else
if ((filepos = _lseek(fd, 0L, SEEK_CUR)) < 0L)
#endif
return(-1L);
if (!bigbuf(stream)) /* _IONBF or no buffering designated */
return(filepos - stream->_cnt);
offset = stream->_ptr - stream->_base;
#ifndef _POSIX_
if (stream->_flag & (_IOWRT|_IOREAD)) {
if (_osfile[fd] & FTEXT)
for (p = stream->_base; p < stream->_ptr; p++)
if (*p == '\n') /* adjust for '\r' */
offset++;
}
else if (!(stream->_flag & _IORW)) {
errno=EINVAL;
return(-1L);
}
#endif
if (filepos == 0L)
return((long)offset);
if (stream->_flag & _IOREAD) /* go to preceding sector */
if (stream->_cnt == 0) /* filepos holds correct location */
offset = 0;
else {
/* Subtract out the number of unread bytes left in the
buffer. [We can't simply use _iob[]._bufsiz because
the last read may have hit EOF and, thus, the buffer
was not completely filled.] */
rdcnt = stream->_cnt + (stream->_ptr - stream->_base);
#ifndef _POSIX_
/* If text mode, adjust for the cr/lf substitution. If
binary mode, we're outta here. */
if (_osfile[fd] & FTEXT) {
/* (1) If we're not at eof, simply copy _bufsiz
onto rdcnt to get the # of untranslated
chars read. (2) If we're at eof, we must
look through the buffer expanding the '\n'
chars one at a time. */
/* [NOTE: Performance issue -- it is faster to
do the two _lseek() calls than to blindly go
through and expand the '\n' chars regardless
of whether we're at eof or not.] */
if (_lseek(fd, 0L, 2) == filepos) {
max = stream->_base + rdcnt;
for (p = stream->_base; p < max; p++)
if (*p == '\n')
/* adjust for '\r' */
rdcnt++;
/* If last byte was ^Z, the lowio read
didn't tell us about it. Check flag
and bump count, if necessary. */
if (stream->_flag & _IOCTRLZ)
++rdcnt;
}
else {
_lseek(fd, filepos, 0);
rdcnt = stream->_bufsiz;
/* If first byte in untranslated buffer
was a '\n', assume it was preceeded
by a '\r' which was discarded by the
previous read operation and count
the '\n'. */
if (_osfile[fd] & FCRLF)
++rdcnt;
}
} /* end if FTEXT */
#endif /* !_POSIX_ */
filepos -= (long)rdcnt;
} /* end else stream->_cnt != 0 */
return(filepos + (long)offset);
}
|