Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / stdio / flushbuf.c
1 /*
2  * flushbuf.c - flush a buffer
3  */
4 /* $Id: flushbuf.c,v 1.9 1996/04/24 13:06:00 ceriel Exp $ */
5
6 #include        <stdio.h>
7 #include        <stdlib.h>
8 #include        "loc_incl.h"
9
10 #include        <sys/types.h>
11
12 off_t _lseek(int fildes, off_t offset, int whence);
13 int _write(int d, const char *buf, int nbytes);
14 int _isatty(int d);
15 extern void (*_clean)(void);
16
17 static int
18 do_write(int d, char *buf, int nbytes)
19 {
20         int c;
21
22         /* POSIX actually allows write() to return a positive value less
23            than nbytes, so loop ...
24         */
25         while ((c = _write(d, buf, nbytes)) > 0 && c < nbytes) {
26                 nbytes -= c;
27                 buf += c;
28         }
29         return c > 0;
30 }
31
32 int
33 __flushbuf(int c, FILE * stream)
34 {
35         _clean = __cleanup;
36         if (fileno(stream) < 0) return EOF;
37         if (!io_testflag(stream, _IOWRITE)) return EOF;
38         if (io_testflag(stream, _IOREADING) && !feof(stream)) return EOF;
39
40         stream->_flags &= ~_IOREADING;
41         stream->_flags |= _IOWRITING;
42         if (!io_testflag(stream, _IONBF)) {
43                 if (!stream->_buf) {
44                         if (stream == stdout && _isatty(fileno(stdout))) {
45                                 if (!(stream->_buf =
46                                             (unsigned char *) malloc(BUFSIZ))) {
47                                         stream->_flags |= _IONBF;
48                                 } else {
49                                         stream->_flags |= _IOLBF|_IOMYBUF;
50                                         stream->_bufsiz = BUFSIZ;
51                                         stream->_count = -1;
52                                 }
53                         } else {
54                                 if (!(stream->_buf =
55                                             (unsigned char *) malloc(BUFSIZ))) {
56                                         stream->_flags |= _IONBF;
57                                 } else {
58                                         stream->_flags |= _IOMYBUF;
59                                         stream->_bufsiz = BUFSIZ;
60                                         if (!io_testflag(stream, _IOLBF))
61                                                 stream->_count = BUFSIZ - 1;
62                                         else    stream->_count = -1;
63                                 }
64                         }
65                         stream->_ptr = stream->_buf;
66                 }
67         }
68
69         if (io_testflag(stream, _IONBF)) {
70                 char c1 = c;
71
72                 stream->_count = 0;
73                 if (io_testflag(stream, _IOAPPEND)) {
74                         if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
75                                 stream->_flags |= _IOERR;
76                                 return EOF;
77                         }
78                 }
79                 if (_write(fileno(stream), &c1, 1) != 1) {
80                         stream->_flags |= _IOERR;
81                         return EOF;
82                 }
83                 return (unsigned char) c;
84         } else if (io_testflag(stream, _IOLBF)) {
85                 *stream->_ptr++ = c;
86                 /* stream->_count has been updated in putc macro. */
87                 if (c == '\n' || stream->_count == -stream->_bufsiz) {
88                         int count = -stream->_count;
89
90                         stream->_ptr  = stream->_buf;
91                         stream->_count = 0;
92
93                         if (io_testflag(stream, _IOAPPEND)) {
94                                 if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
95                                         stream->_flags |= _IOERR;
96                                         return EOF;
97                                 }
98                         }
99                         if (! do_write(fileno(stream), (char *)stream->_buf,
100                                         count)) {
101                                 stream->_flags |= _IOERR;
102                                 return EOF;
103                         }
104                 }
105         } else {
106                 int count = stream->_ptr - stream->_buf;
107
108                 stream->_count = stream->_bufsiz - 1;
109                 stream->_ptr = stream->_buf + 1;
110
111                 if (count > 0) {
112                         if (io_testflag(stream, _IOAPPEND)) {
113                                 if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
114                                         stream->_flags |= _IOERR;
115                                         return EOF;
116                                 }
117                         }
118                         if (! do_write(fileno(stream), (char *)stream->_buf, count)) {
119                                 *(stream->_buf) = c;
120                                 stream->_flags |= _IOERR;
121                                 return EOF;
122                         }
123                 }
124                 *(stream->_buf) = c;
125         }
126         return (unsigned char) c;
127 }