netinet/in.h: add IPPROTO_MH
[uclibc-ng.git] / libc / stdio / _adjust_pos.c
blobbc6e905559126322b8997234404c912397ae98e1
1 /* Copyright (C) 2004 Manuel Novoa III <mjn3@codepoet.org>
3 * GNU Library General Public License (LGPL) version 2 or later.
5 * Dedicated to Toni. See uClibc/DEDICATION.mjn3 for details.
6 */
8 #include "_stdio.h"
10 /* Both ftell() and fseek() (for SEEK_CUR) need to correct the stream's
11 * position to take into account buffered data and ungotten chars.
13 * If successful, store corrected position in *pos and return >= 0.
14 * Otherwise return < 0.
16 * If position is unrepresentable, set errno to EOVERFLOW.
19 int attribute_hidden __stdio_adjust_position(register FILE * __restrict stream,
20 register __offmax_t *pos)
22 __offmax_t oldpos;
23 int corr;
25 if ((corr = stream->__modeflags & __MASK_READING) != 0) {
26 --corr; /* Correct for ungots. Assume narrow, and fix below. */
29 #ifdef __UCLIBC_HAS_WCHAR__
30 if (corr && __STDIO_STREAM_IS_WIDE(stream)) {
31 /* A wide stream and we have at least one ungotten wchar.
32 * If it is a user ungot, we need to fail since position
33 * is unspecified as per C99. */
34 if ((corr > 1) || stream->__ungot[1]) { /* User ungetwc, */
35 return -1; /* so position is undefined. */
37 corr -= (1 + stream->__ungot_width[1]);
38 if (stream->__state.__mask > 0) { /* Incomplete (bad?) mb char. */
39 corr -= stream->__ungot_width[0];
42 #endif
44 #ifdef __STDIO_BUFFERS
45 corr += (((__STDIO_STREAM_IS_WRITING(stream))
46 ? stream->__bufstart : stream->__bufread)
47 - stream->__bufpos);
48 #endif
50 oldpos = *pos;
52 /* Range checking cases:
53 * (pos - corr > pos) && (corr > 0) : underflow? return -corr < 0
54 * (pos - corr > pos) && (corr < 0) : ok .. return -corr > 0
55 * (pos - corr <= pos) && (corr >= 0) : ok .. return corr > 0
56 * (pos - corr <= pos) && (corr < 0) : overflow .. return corr < 0
59 if ((*pos -= corr) > oldpos) {
60 corr = -corr;
63 if (corr < 0) {
64 __set_errno(EOVERFLOW);
67 return corr;