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