fgetws implementation.
[kopensolaris-gnu/glibc.git] / stdio / fwrite.c
index 9fa3f4a..2369743 100644 (file)
@@ -1,22 +1,21 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-This file is part of the GNU C Library.
+/* Copyright (C) 1991, 92, 93, 94, 96, 97, 98 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
 
-The GNU C Library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Library General Public License as
-published by the Free Software Foundation; either version 2 of the
-License, or (at your option) any later version.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public License as
+   published by the Free Software Foundation; either version 2 of the
+   License, or (at your option) any later version.
 
-The GNU C Library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-Library General Public License for more details.
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
 
-You should have received a copy of the GNU Library General Public
-License along with the GNU C Library; see the file COPYING.LIB.  If
-not, write to the Free Software Foundation, Inc., 675 Mass Ave,
-Cambridge, MA 02139, USA.  */
+   You should have received a copy of the GNU Library General Public
+   License along with the GNU C Library; see the file COPYING.LIB.  If not,
+   write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.  */
 
-#include <ansidecl.h>
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
@@ -24,24 +23,26 @@ Cambridge, MA 02139, USA.  */
 
 /* Write NMEMB chunks of SIZE bytes each from PTR onto STREAM.  */
 size_t
-DEFUN(fwrite, (ptr, size, nmemb, stream),
-      CONST PTR ptr AND size_t size AND
-      size_t nmemb AND register FILE *stream)
+fwrite (ptr, size, nmemb, stream)
+     const void *ptr;
+     size_t size;
+     size_t nmemb;
+     register FILE *stream;
 {
-  register CONST char *p = (CONST char *) ptr;
+  register const unsigned char *p = (const unsigned char *) ptr;
   register size_t to_write = size * nmemb;
   register size_t written = 0;
   int newlinep;
   size_t buffer_space;
-  char default_func;
+  int default_func;
 
-  if (!__validfp(stream) || !stream->__mode.__write)
+  if (!__validfp (stream) || !stream->__mode.__write)
     {
-      errno = EINVAL;
+      __set_errno (EINVAL);
       return 0;
     }
 
-  if (ferror(stream))
+  if (ferror (stream))
     return 0;
   if (p == NULL || to_write == 0)
     return 0;
@@ -51,7 +52,7 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
       /* This stream has never been seen before.
         Calling __flshfp will give it a buffer
         and I/O functions if it needs them.  */
-      if (__flshfp(stream, *p++) == EOF)
+      if (__flshfp (stream, *p++) == EOF)
        return 0;
       if (--to_write == 0)
        return 1;
@@ -62,11 +63,17 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
   default_func
     = stream->__room_funcs.__output == __default_room_functions.__output;
 
-  if (__stdio_check_offset (stream) == EOF)
-    {
-      stream->__error = 1;
-      goto done;
-    }
+  {
+    int save = errno;
+
+    if (__stdio_check_offset (stream) == EOF && errno != ESPIPE)
+      {
+       stream->__error = 1;
+       goto done;
+      }
+
+    __set_errno (save);
+  }
 
   if (stream->__buffer == NULL && default_func &&
       stream->__offset == stream->__target)
@@ -75,13 +82,17 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
        buffer-flushing function, so we just do a straight write.  */
     {
       int count = (stream->__io_funcs.__write == NULL ? to_write :
-                  (*stream->__io_funcs.__write)(stream->__cookie, p,
-                                                to_write));
+                  (*stream->__io_funcs.__write) (stream->__cookie,
+                                                 (const char *) p,
+                                                 to_write));
       if (count > 0)
        {
          written += count;
-         stream->__offset += count;
-         stream->__target = stream->__offset;
+         if (stream->__offset != -1)
+           {
+             stream->__offset += count;
+             stream->__target = stream->__offset;
+           }
          to_write -= count;
          p += count;
        }
@@ -95,7 +106,7 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
   buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
 
   newlinep = (stream->__linebuf &&
-             memchr((CONST PTR) p, '\n', to_write) != NULL);
+             memchr ((const void *) p, '\n', to_write) != NULL);
 
   if (newlinep && stream->__bufp == stream->__buffer &&
       stream->__offset == stream->__target)
@@ -109,46 +120,74 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
         We can't do much better than putc.  */
       while (to_write-- > 0)
        {
-         if (__flshfp(stream, *p++) == EOF)
+         if (__flshfp (stream, *p++) == EOF)
            break;
          else
            ++written;
        }
     }
   else if (!default_func || buffer_space >= to_write)
-  fill_buffer:
-    /* There is enough room in the buffer for everything we
-       want to write or the user has specified his own output
-       buffer-flushing/expanding function.  */
-    while (to_write > 0)
-      {
-       register size_t n = to_write;
-
-       if (n > buffer_space)
-         n = buffer_space;
-
-       buffer_space -= n;
-
-       written += n;
-       to_write -= n;
-
-       if (n < 20)
-         while (n-- > 0)
-           *stream->__bufp++ = *p++;
-       else
-         {
-           memcpy((PTR) stream->__bufp, (PTR) p, n);
-           stream->__bufp += n;
-           p += n;
-         }
-
-       if (buffer_space == 0 || (to_write == 0 && newlinep))
-         {
-           /* We've filled the buffer, so flush it.  */
-           if (fflush(stream) == EOF)
-             break;
-         }
-      }
+    {
+      /* There is enough room in the buffer for everything we want to write
+        or the user has specified his own output buffer-flushing/expanding
+        function.  */
+    fill_buffer:
+      while (to_write > 0)
+       {
+         register size_t n = to_write;
+
+         if (n > buffer_space)
+           n = buffer_space;
+
+         buffer_space -= n;
+
+         written += n;
+         to_write -= n;
+
+         if (n < 20)
+           while (n-- > 0)
+             *stream->__bufp++ = *p++;
+         else
+           {
+             memcpy ((void *) stream->__bufp, (void *) p, n);
+             stream->__bufp += n;
+             p += n;
+           }
+
+         if (to_write == 0)
+           /* Done writing.  */
+           break;
+         else if (buffer_space == 0)
+           {
+             /* We have filled the buffer, so flush it.  */
+             if (fflush (stream) == EOF)
+               break;
+
+             /* Reset our record of the space available in the buffer,
+                since we have just flushed it.  */
+           check_space:
+             buffer_space = (stream->__bufsize -
+                             (stream->__bufp - stream->__buffer));
+             if (buffer_space == 0)
+               {
+                 /* With a custom output-room function, flushing might
+                    not create any buffer space.  Try writing a single
+                    character to create the space.  */
+                 if (__flshfp (stream, *p++) == EOF)
+                   goto done;
+                 ++written;
+                 --to_write;
+                 goto check_space;
+               }
+           }
+       }
+
+      /* We have written all the data into the buffer.  If we are
+        line-buffered and just put a newline in the buffer, flush now to
+        make sure it gets out.  */
+      if (newlinep)
+       fflush (stream);
+    }
   else
     {
       /* It won't all fit in the buffer.  */
@@ -156,14 +195,14 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
       if (stream->__bufp != stream->__buffer)
        {
          /* There are characters in the buffer.  Flush them.  */
-         if (__flshfp(stream, EOF) == EOF)
+         if (__flshfp (stream, EOF) == EOF)
            goto done;
        }
 
       /* The buffer has been flushed.
         Now either fill it or write directly.  */
 
-      buffer_space = stream->__put_limit - stream->__bufp;
+      buffer_space = stream->__bufsize - (stream->__bufp - stream->__buffer);
 
       if (stream->__offset == stream->__target &&
          (buffer_space < to_write || newlinep))
@@ -179,3 +218,5 @@ DEFUN(fwrite, (ptr, size, nmemb, stream),
  done:;
   return (size_t) written / size;
 }
+
+weak_alias (fwrite, fwrite_unlocked)