home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / glibc-1.06 / mach / devstream.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-02  |  3.8 KB  |  171 lines

  1. /* stdio on a Mach device port.
  2.    Translates \n to \r\n 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. #include <errno.h>
  26. #include <string.h>
  27.  
  28. static int
  29. input (FILE *f)
  30. {
  31.   kern_return_t err;
  32.   char *buffer;
  33.   size_t to_read, nread;
  34.   char c;
  35.  
  36.   if (f->__buffer == NULL)
  37.     {
  38.       buffer = &c;
  39.       to_read = 1;
  40.     }
  41.   else
  42.     {
  43.       buffer = f->__buffer;
  44.       to_read = f->__bufsize;
  45.     }
  46.  
  47.   f->__eof = 0;
  48.  
  49.   if (err = device_read_inband ((device_t) f->__cookie, 0, f->__target,
  50.                 to_read, buffer, &nread))
  51.     {
  52.       f->__error = 1;
  53.       f->__bufp = f->__get_limit = f->__put_limit = f->__buffer;
  54.       errno = err;
  55.       return EOF;
  56.     }
  57.  
  58.   if (f->__buffer == NULL)
  59.     return (unsigned char) c;
  60.  
  61.   f->__get_limit = f->__buffer + nread;
  62.   f->__bufp = f->__buffer;
  63.   f->__put_limit = f->__buffer + (f->__mode.__write ? f->__bufsize : 0);
  64.   return (unsigned char) *f->__bufp++;
  65. }
  66.  
  67. static void
  68. output (FILE *f, int c)
  69. {
  70.   void write_some (const char *p, size_t to_write)
  71.     {
  72.       kern_return_t err;
  73.       int wrote;
  74.       while (to_write > 0)
  75.     {
  76.       if (err = device_write_inband ((device_t) f->__cookie, 0,
  77.                      f->__target, p, to_write, &wrote))
  78.         {
  79.           errno = err;
  80.           f->__error = 1;
  81.           break;
  82.         }
  83.       p += wrote;
  84.       to_write -= wrote;
  85.       f->__target += wrote;
  86.     }
  87.     }
  88.   void write_crlf (void)
  89.     {
  90.       static const char crlf[] = "\r\n";
  91.       write_some (crlf, 2);
  92.     }
  93.  
  94.   if (f->__buffer == NULL)
  95.     {
  96.       /* The stream is unbuffered.  */
  97.  
  98.       if (c == '\n')
  99.     write_crlf ();
  100.       else if (c != EOF)
  101.     {
  102.       char cc = (unsigned char) c;
  103.       write_some (&cc, 1);
  104.     }
  105.  
  106.       return;
  107.     }
  108.  
  109.   if (f->__put_limit == f->__buffer)
  110.     {
  111.       /* Prime the stream for writing.  */
  112.       f->__put_limit = f->__buffer + f->__bufsize;
  113.       f->__bufp = f->__buffer;
  114.       if (c != EOF)
  115.     {
  116.       *f->__bufp++ = (unsigned char) c;
  117.       c = EOF;
  118.     }
  119.     }
  120.  
  121.   {
  122.     /* Search for newlines (LFs) in the buffer.  */
  123.  
  124.     char *start = f->__buffer, *p = start;
  125.  
  126.     while (!ferror (f) && (p = memchr (p, '\n', f->__bufp - start)))
  127.       {
  128.     /* Found one.  Replace it with a CR and write out through that CR.  */
  129.  
  130.     *p = '\r';
  131.     write_some (start, p + 1 - start);
  132.  
  133.     /* Change it back to an LF; the next iteration will write it out
  134.        first thing.  Start the next searching iteration one char later.  */
  135.  
  136.     start = p;
  137.     *p++ = '\n';
  138.       }
  139.  
  140.     /* Write the remainder of the buffer.  */
  141.  
  142.     if (!ferror (f))
  143.       write_some (start, f->__bufp - start);
  144.   }
  145.  
  146.   f->__bufp = f->__buffer;
  147.  
  148.   if (c != EOF && !ferror (f))
  149.     {
  150.       if (f->__linebuf && (unsigned char) c == '\n')
  151.     write_crlf ();
  152.       else
  153.     *f->__bufp++ = (unsigned char) c;
  154.     }
  155. }
  156.  
  157. FILE *
  158. mach_open_devstream (device_t dev, const char *mode)
  159. {
  160.   FILE *stream = fopencookie ((void *) dev, mode, __default_io_functions);
  161.   if (stream == NULL)
  162.     return NULL;
  163.  
  164.   stream->__room_funcs.__input = input;
  165.   stream->__room_funcs.__output = output;
  166.   stream->__io_funcs.__close = device_close;
  167.   stream->__seen = 1;
  168.  
  169.   return stream;
  170. }
  171.