Formerly ../mach/devstream.c.~5~
[kopensolaris-gnu/glibc.git] / mach / devstream.c
1 /* stdio on a Mach device port.
2    Translates \n to \r on output.
3
4 Copyright (C) 1992 Free Software Foundation, Inc.
5 This file is part of the GNU C Library.
6
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
11
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 Library General Public License for more details.
16
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB.  If
19 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
20 Cambridge, MA 02139, USA.  */
21
22 #include <stdio.h>
23 #include <mach.h>
24 #include <device/device.h>
25
26 static int
27 input (FILE *f)
28 {
29   error_t err;
30   char *buffer;
31   size_t to_read;
32   char c;
33
34   if (f->__buffer == NULL)
35     {
36       buffer = &c;
37       to_read = 1;
38     }
39   else
40     {
41       buffer = f->__buffer;
42       to_read = f->__bufsize;
43     }
44
45   f->__eof = 0;
46
47   if (err = device_read_inband ((device_t) cookie, 0, f->__target, to_read,
48                                 buffer, &nread))
49     {
50       f->__error = 1;
51       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
52       errno = err;
53       return EOF;
54     }
55
56   if (f->__buffer == NULL)
57     return (unsigned char) c;
58
59   f->__get_limit = f->__buffer + nread;
60   f->__bufp = f->__buffer;
61   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
62   return (unsigned char *) *f->__bufp++;
63 }
64
65 static void
66 output (FILE *f, int c)
67 {
68   error_t err;
69   size_t to_write;
70   char *p;
71
72   if (f->__buffer == NULL)
73     {
74       if (c != EOF)
75         {
76           char cc = (unsigned char) c;
77           int wrote;
78           if (cc == '\n')
79             cc = '\r';
80           if ((err = device_write_inband ((device_t) f->__cookie, 0,
81                                           f->__target, &cc, 1, &wrote)) ||
82               wrote != 1)
83             {
84               errno = err;
85               f->__error = 1;
86             }
87         }
88       ++f->__target;
89       return;
90     }
91
92   if (f->__put_limit == f->__buffer)
93     {
94       f->__put_limit = f->__buffer + f->__bufsize;
95       f->__bufp = f->__buffer;
96       if (c != EOF)
97         {
98           *f->__bufp++ = (unsigned char) c;
99           c = EOF;
100         }
101     }
102
103   to_write = f->__bufp - f->__buffer;
104   p = f->__buffer;
105   while (1)
106     {
107       char *p2 = memchr (p, '\n', to_write);
108       if (p2 == NULL)
109         break;
110       *p2++ = '\r';
111       to_write -= p2 - p;
112       p = p2;
113     }
114
115   to_write = f->__bufp - f->__buffer;
116   p = f->__buffer;
117   while (to_write > 0)
118     {
119       int wrote;
120       if (err = device_write_inband ((device_t) f->__cookie, 0, f->__target,
121                                      p, to_write, &wrote))
122         {
123           errno = EIO;
124           f->__error = 1;
125           break;
126         }
127       p += wrote;
128       to_write -= wrote;
129       f->__target += wrote;
130     }
131
132   f->__bufp = f->__buffer;
133
134   if (c != EOF && !ferror (f))
135     {
136       if (f->__linebuf && (unsigned char) c == '\n')
137         {
138           static const char nl = '\r';
139           if ((err = device_write_inband ((device_t) f->__cookie, 0,
140                                           f->__target, &nl, 1, &wrote)) ||
141               wrote != 1)
142             {
143               errno = EIO;
144               f->__error = 1;
145             }
146           else
147             ++f->__target;
148         }
149       else
150         *f->__bufp++ = (unsigned char) c;
151     }
152 }
153
154 FILE *
155 mach_open_devstream (device_t dev, const char *mode)
156 {
157   FILE *stream = fopencookie (dev, mode, __default_io_functions);
158   if (stream == NULL)
159     return NULL;
160
161   stream->__room_funcs.__input = input;
162   stream->__room_funcs.__output = output;
163   stream->__io_funcs.__close = device_close;
164   stream->__seen = 1;
165
166   retrun stream;
167 }