source: trunk/libs/newlib/src/newlib/libc/stdio/setvbuf.c @ 567

Last change on this file since 567 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 6.0 KB
Line 
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms are permitted
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley.  The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16 */
17
18/*
19FUNCTION
20<<setvbuf>>---specify file or stream buffering
21
22INDEX
23        setvbuf
24
25SYNOPSIS
26        #include <stdio.h>
27        int setvbuf(FILE *<[fp]>, char *<[buf]>,
28                    int <[mode]>, size_t <[size]>);
29
30DESCRIPTION
31Use <<setvbuf>> to specify what kind of buffering you want for the
32file or stream identified by <[fp]>, by using one of the following
33values (from <<stdio.h>>) as the <[mode]> argument:
34
35o+
36o _IONBF
37Do not use a buffer: send output directly to the host system for the
38file or stream identified by <[fp]>.
39
40o _IOFBF
41Use full output buffering: output will be passed on to the host system
42only when the buffer is full, or when an input operation intervenes.
43
44o _IOLBF
45Use line buffering: pass on output to the host system at every
46newline, as well as when the buffer is full, or when an input
47operation intervenes.
48o-
49
50Use the <[size]> argument to specify how large a buffer you wish.  You
51can supply the buffer itself, if you wish, by passing a pointer to a
52suitable area of memory as <[buf]>.  Otherwise, you may pass <<NULL>>
53as the <[buf]> argument, and <<setvbuf>> will allocate the buffer.
54
55WARNINGS
56You may only use <<setvbuf>> before performing any file operation other
57than opening the file.
58
59If you supply a non-null <[buf]>, you must ensure that the associated
60storage continues to be available until you close the stream
61identified by <[fp]>.
62
63RETURNS
64A <<0>> result indicates success, <<EOF>> failure (invalid <[mode]> or
65<[size]> can cause failure).
66
67PORTABILITY
68Both ANSI C and the System V Interface Definition (Issue 2) require
69<<setvbuf>>. However, they differ on the meaning of a <<NULL>> buffer
70pointer: the SVID issue 2 specification says that a <<NULL>> buffer
71pointer requests unbuffered output.  For maximum portability, avoid
72<<NULL>> buffer pointers.
73
74Both specifications describe the result on failure only as a
75nonzero value.
76
77Supporting OS subroutines required: <<close>>, <<fstat>>, <<isatty>>,
78<<lseek>>, <<read>>, <<sbrk>>, <<write>>.
79*/
80
81#include <_ansi.h>
82#include <stdio.h>
83#include <stdlib.h>
84#include "local.h"
85
86/*
87 * Set one of the three kinds of buffering, optionally including a buffer.
88 */
89
90int
91setvbuf (register FILE * fp,
92       char *buf,
93       register int mode,
94       register size_t size)
95{
96  int ret = 0;
97  struct _reent *reent = _REENT;
98  size_t iosize;
99  int ttyflag;
100
101  CHECK_INIT (reent, fp);
102
103  /*
104   * Verify arguments.  The `int' limit on `size' is due to this
105   * particular implementation.  Note, buf and size are ignored
106   * when setting _IONBF.
107   */
108  if (mode != _IONBF)
109    if ((mode != _IOFBF && mode != _IOLBF) || (int)(_POINTER_INT) size < 0)
110      return (EOF);
111
112
113  /*
114   * Write current buffer, if any; drop read count, if any.
115   * Make sure putc() will not think fp is line buffered.
116   * Free old buffer if it was from malloc().  Clear line and
117   * non buffer flags, and clear malloc flag.
118   */
119  _newlib_flockfile_start (fp);
120  _fflush_r (reent, fp);
121  if (HASUB(fp))
122    FREEUB(reent, fp);
123  fp->_r = fp->_lbfsize = 0;
124  if (fp->_flags & __SMBF)
125    _free_r (reent, (void *) fp->_bf._base);
126  fp->_flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SNPT | __SEOF);
127
128  if (mode == _IONBF)
129    goto nbf;
130
131  /*
132   * Find optimal I/O size for seek optimization.  This also returns
133   * a `tty flag' to suggest that we check isatty(fd), but we do not
134   * care since our caller told us how to buffer.
135   */
136  fp->_flags |= __swhatbuf_r (reent, fp, &iosize, &ttyflag);
137  if (size == 0)
138    {
139      buf = NULL;
140      size = iosize;
141    }
142
143  /* Allocate buffer if needed. */
144  if (buf == NULL)
145    {
146      if ((buf = malloc (size)) == NULL)
147        {
148          /*
149           * Unable to honor user's request.  We will return
150           * failure, but try again with file system size.
151           */
152          ret = EOF;
153          if (size != iosize)
154            {
155              size = iosize;
156              buf = malloc (size);
157            }
158        }
159      if (buf == NULL)
160        {
161          /* No luck; switch to unbuffered I/O. */
162nbf:
163          fp->_flags |= __SNBF;
164          fp->_w = 0;
165          fp->_bf._base = fp->_p = fp->_nbuf;
166          fp->_bf._size = 1;
167          _newlib_flockfile_exit (fp);
168          return (ret);
169        }
170      fp->_flags |= __SMBF;
171    }
172
173  /*
174   * We're committed to buffering from here, so make sure we've
175   * registered to flush buffers on exit.
176   */
177  if (!reent->__sdidinit)
178    __sinit(reent);
179
180#ifdef _FSEEK_OPTIMIZATION
181  /*
182   * Kill any seek optimization if the buffer is not the
183   * right size.
184   *
185   * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
186   */
187  if (size != iosize)
188     fp->_flags |= __SNPT;
189#endif
190
191  /*
192   * Fix up the FILE fields, and set __cleanup for output flush on
193   * exit (since we are buffered in some way).
194   */
195  if (mode == _IOLBF)
196    fp->_flags |= __SLBF;
197  fp->_bf._base = fp->_p = (unsigned char *) buf;
198  fp->_bf._size = size;
199  /* fp->_lbfsize is still 0 */
200  if (fp->_flags & __SWR)
201    {
202      /*
203       * Begin or continue writing: see __swsetup().  Note
204       * that __SNBF is impossible (it was handled earlier).
205       */
206      if (fp->_flags & __SLBF)
207        {
208          fp->_w = 0;
209          fp->_lbfsize = -fp->_bf._size;
210        }
211      else
212        fp->_w = size;
213    }
214  else
215    {
216      /* begin/continue reading, or stay in intermediate state */
217      fp->_w = 0;
218    }
219
220  _newlib_flockfile_end (fp);
221  return 0;
222}
Note: See TracBrowser for help on using the repository browser.