OSDN Git Service

9d853f94dcd12b98c34cfbd94fc5d2c6c671dead
[pf3gnuchains/pf3gnuchains4x.git] / newlib / libc / stdio / refill.c
1 /*
2  * Copyright (c) 1990 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 /* No user fns here.  Pesch 15apr92. */
18
19 #include <_ansi.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include "local.h"
24
25 static int
26 _DEFUN(lflush, (fp),
27        FILE *fp)
28 {
29   if ((fp->_flags & (__SLBF | __SWR)) == (__SLBF | __SWR))
30     return fflush (fp);
31   return 0;
32 }
33
34 /*
35  * Refill a stdio buffer.
36  * Return EOF on eof or error, 0 otherwise.
37  */
38
39 int
40 _DEFUN(__srefill_r, (ptr, fp),
41        struct _reent * ptr _AND
42        register FILE * fp)
43 {
44   /* make sure stdio is set up */
45
46   CHECK_INIT (ptr, fp);
47
48   ORIENT (fp, -1);
49
50   fp->_r = 0;                   /* largely a convenience for callers */
51
52 #ifndef __CYGWIN__
53   /* SysV does not make this test; take it out for compatibility */
54   if (fp->_flags & __SEOF)
55     return EOF;
56 #endif
57
58   /* if not already reading, have to be reading and writing */
59   if ((fp->_flags & __SRD) == 0)
60     {
61       if ((fp->_flags & __SRW) == 0)
62         {
63           ptr->_errno = EBADF;
64           fp->_flags |= __SERR;
65           return EOF;
66         }
67       /* switch to reading */
68       if (fp->_flags & __SWR)
69         {
70           if (_fflush_r (ptr, fp))
71             return EOF;
72           fp->_flags &= ~__SWR;
73           fp->_w = 0;
74           fp->_lbfsize = 0;
75         }
76       fp->_flags |= __SRD;
77     }
78   else
79     {
80       /*
81        * We were reading.  If there is an ungetc buffer,
82        * we must have been reading from that.  Drop it,
83        * restoring the previous buffer (if any).  If there
84        * is anything in that buffer, return.
85        */
86       if (HASUB (fp))
87         {
88           FREEUB (ptr, fp);
89           if ((fp->_r = fp->_ur) != 0)
90             {
91               fp->_p = fp->_up;
92               return 0;
93             }
94         }
95     }
96
97   if (fp->_bf._base == NULL)
98     __smakebuf_r (ptr, fp);
99
100   /*
101    * Before reading from a line buffered or unbuffered file,
102    * flush all line buffered output files, per the ANSI C
103    * standard.
104    */
105   if (fp->_flags & (__SLBF | __SNBF))
106     {
107       /* Ignore this file in _fwalk to avoid potential deadlock. */
108       short orig_flags = fp->_flags;
109       fp->_flags = 1;
110       _CAST_VOID _fwalk (_GLOBAL_REENT, lflush);
111       fp->_flags = orig_flags;
112
113       /* Now flush this file without locking it. */
114       if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
115         __sflush_r (ptr, fp);
116     }
117
118   fp->_p = fp->_bf._base;
119   fp->_r = fp->_read (ptr, fp->_cookie, (char *) fp->_p, fp->_bf._size);
120 #ifndef __CYGWIN__
121   if (fp->_r <= 0)
122 #else
123   if (fp->_r > 0)
124     fp->_flags &= ~__SEOF;
125   else
126 #endif
127     {
128       if (fp->_r == 0)
129         fp->_flags |= __SEOF;
130       else
131         {
132           fp->_r = 0;
133           fp->_flags |= __SERR;
134         }
135       return EOF;
136     }
137   return 0;
138 }