Initial revision
[kopensolaris-gnu/glibc.git] / mach / devstream.c
1 /* stdio on a Mach device port.
2    Translates \n to \r on output.  */
3
4 #include <ansidecl.h>
5 #include <stdio.h>
6 #include <mach.h>
7 #include <mach/device.h>
8
9 static int
10 input (FILE *f)
11 {
12   error_t err;
13   char *buffer;
14   size_t to_read;
15   char c;
16
17   if (f->__buffer == NULL)
18     {
19       buffer = &c;
20       to_read = 1;
21     }
22   else
23     {
24       buffer = f->__buffer;
25       to_read = f->__bufsize;
26     }
27
28   f->__eof = 0;
29
30   if (err = device_read_inband ((device_t) cookie, 0, f->__target, to_read,
31                                 buffer, &nread))
32     {
33       errno = EIO;
34       f->__error = 1;
35       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
36       return EOF;
37     }
38
39   if (f->__buffer == NULL)
40     return (unsigned char) c;
41
42   f->__get_limit = f->__buffer + nread;
43   f->__bufp = f->__buffer;
44   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
45   return (unsigned char *) *f->__bufp++;
46 }
47
48 static void
49 output (FILE *f, int c)
50 {
51   error_t err;
52   size_t to_write;
53   char *p;
54
55   if (f->__buffer == NULL)
56     {
57       if (c != EOF)
58         {
59           char cc = (unsigned char) c;
60           int wrote;
61           if (cc == '\n')
62             cc = '\r';
63           if ((err = device_write_inband ((device_t) f->__cookie, 0,
64                                           f->__target, &cc, 1, &wrote)) ||
65               wrote != 1)
66             {
67               errno = EIO;
68               f->__error = 1;
69             }
70         }
71       ++f->__target;
72       return;
73     }
74
75   if (f->__put_limit == f->__buffer)
76     {
77       f->__put_limit = f->__buffer + f->__bufsize;
78       f->__bufp = f->__buffer;
79       if (c != EOF)
80         {
81           *f->__bufp++ = (unsigned char) c;
82           c = EOF;
83         }
84     }
85
86   to_write = f->__bufp - f->__buffer;
87   p = f->__buffer;
88   while (1)
89     {
90       char *p2 = memchr (p, '\n', to_write);
91       if (p2 == NULL)
92         break;
93       *p2++ = '\r';
94       to_write -= p2 - p;
95       p = p2;
96     }
97
98   to_write = f->__bufp - f->__buffer;
99   p = f->__buffer;
100   while (to_write > 0)
101     {
102       int wrote;
103       if (err = device_write_inband ((device_t) f->__cookie, 0, f->__target,
104                                      p, to_write, &wrote))
105         {
106           errno = EIO;
107           f->__error = 1;
108           break;
109         }
110       p += wrote;
111       to_write -= wrote;
112       f->__target += wrote;
113     }
114
115   f->__bufp = f->__buffer;
116
117   if (c != EOF && !ferror (f))
118     {
119       if (f->__linebuf && (unsigned char) c == '\n')
120         {
121           static const char nl = '\r';
122           if ((err = device_write_inband ((device_t) f->__cookie, 0,
123                                           f->__target, &nl, 1, &wrote)) ||
124               wrote != 1)
125             {
126               errno = EIO;
127               f->__error = 1;
128             }
129           else
130             ++f->__target;
131         }
132       else
133         *f->__bufp++ = (unsigned char) c;
134     }
135 }
136
137 FILE *
138 mach_open_devstream (device_t dev)
139 {
140   FILE *stream = __newstream ();
141   if (stream == NULL)
142     return NULL;
143
144   stream->__cookie = (void *) dev;
145   stream->__room_funcs.__input = input;
146   stream->__room_funcs.__output = output;
147   stream->__io_funcs.__close = device_close;
148   stream->__seen = 1;
149
150   retrun stream;
151 }