OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [newlib-1.17.0/] [newlib/] [libc/] [stdio/] [funopen.c] - Blame information for rev 868

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 148 jeremybenn
/* Copyright (C) 2007 Eric Blake
2
 * Permission to use, copy, modify, and distribute this software
3
 * is freely granted, provided that this notice is preserved.
4
 */
5
 
6
/*
7
FUNCTION
8
<<funopen>>, <<fropen>>, <<fwopen>>---open a stream with custom callbacks
9
 
10
INDEX
11
        funopen
12
INDEX
13
        fropen
14
INDEX
15
        fwopen
16
 
17
ANSI_SYNOPSIS
18
        #include <stdio.h>
19
        FILE *funopen(const void *<[cookie]>,
20
                      int (*<[readfn]>) (void *cookie, char *buf, int n),
21
                      int (*<[writefn]>) (void *cookie, const char *buf, int n),
22
                      fpos_t (*<[seekfn]>) (void *cookie, fpos_t off, int whence),
23
                      int (*<[closefn]>) (void *cookie));
24
        FILE *fropen(const void *<[cookie]>,
25
                     int (*<[readfn]>) (void *cookie, char *buf, int n));
26
        FILE *fwopen(const void *<[cookie]>,
27
                     int (*<[writefn]>) (void *cookie, const char *buf, int n));
28
 
29
DESCRIPTION
30
<<funopen>> creates a <<FILE>> stream where I/O is performed using
31
custom callbacks.  At least one of <[readfn]> and <[writefn]> must be
32
provided, which determines whether the stream behaves with mode <"r">,
33
<"w">, or <"r+">.
34
 
35
<[readfn]> should return -1 on failure, or else the number of bytes
36
read (0 on EOF).  It is similar to <<read>>, except that <int> rather
37
than <size_t> bounds a transaction size, and <[cookie]> will be passed
38
as the first argument.  A NULL <[readfn]> makes attempts to read the
39
stream fail.
40
 
41
<[writefn]> should return -1 on failure, or else the number of bytes
42
written.  It is similar to <<write>>, except that <int> rather than
43
<size_t> bounds a transaction size, and <[cookie]> will be passed as
44
the first argument.  A NULL <[writefn]> makes attempts to write the
45
stream fail.
46
 
47
<[seekfn]> should return (fpos_t)-1 on failure, or else the current
48
file position.  It is similar to <<lseek>>, except that <[cookie]>
49
will be passed as the first argument.  A NULL <[seekfn]> makes the
50
stream behave similarly to a pipe in relation to stdio functions that
51
require positioning.  This implementation assumes fpos_t and off_t are
52
the same type.
53
 
54
<[closefn]> should return -1 on failure, or 0 on success.  It is
55
similar to <<close>>, except that <[cookie]> will be passed as the
56
first argument.  A NULL <[closefn]> merely flushes all data then lets
57
<<fclose>> succeed.  A failed close will still invalidate the stream.
58
 
59
Read and write I/O functions are allowed to change the underlying
60
buffer on fully buffered or line buffered streams by calling
61
<<setvbuf>>.  They are also not required to completely fill or empty
62
the buffer.  They are not, however, allowed to change streams from
63
unbuffered to buffered or to change the state of the line buffering
64
flag.  They must also be prepared to have read or write calls occur on
65
buffers other than the one most recently specified.
66
 
67
The functions <<fropen>> and <<fwopen>> are convenience macros around
68
<<funopen>> that only use the specified callback.
69
 
70
RETURNS
71
The return value is an open FILE pointer on success.  On error,
72
<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
73
function pointer is missing, ENOMEM if the stream cannot be created,
74
or EMFILE if too many streams are already open.
75
 
76
PORTABILITY
77
This function is a newlib extension, copying the prototype from BSD.
78
It is not portable.  See also the <<fopencookie>> interface from Linux.
79
 
80
Supporting OS subroutines required: <<sbrk>>.
81
*/
82
 
83
#include <stdio.h>
84
#include <errno.h>
85
#include <sys/lock.h>
86
#include "local.h"
87
 
88
typedef int (*funread)(void *_cookie, char *_buf, int _n);
89
typedef int (*funwrite)(void *_cookie, const char *_buf, int _n);
90
#ifdef __LARGE64_FILES
91
typedef _fpos64_t (*funseek)(void *_cookie, _fpos64_t _off, int _whence);
92
#else
93
typedef fpos_t (*funseek)(void *_cookie, fpos_t _off, int _whence);
94
#endif
95
typedef int (*funclose)(void *_cookie);
96
 
97
typedef struct funcookie {
98
  void *cookie;
99
  funread readfn;
100
  funwrite writefn;
101
  funseek seekfn;
102
  funclose closefn;
103
} funcookie;
104
 
105
static _READ_WRITE_RETURN_TYPE
106
_DEFUN(funreader, (ptr, cookie, buf, n),
107
       struct _reent *ptr _AND
108
       void *cookie _AND
109
       char *buf _AND
110
       int n)
111
{
112
  int result;
113
  funcookie *c = (funcookie *) cookie;
114
  errno = 0;
115
  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
116
    ptr->_errno = errno;
117
  return result;
118
}
119
 
120
static _READ_WRITE_RETURN_TYPE
121
_DEFUN(funwriter, (ptr, cookie, buf, n),
122
       struct _reent *ptr _AND
123
       void *cookie _AND
124
       const char *buf _AND
125
       int n)
126
{
127
  int result;
128
  funcookie *c = (funcookie *) cookie;
129
  errno = 0;
130
  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
131
    ptr->_errno = errno;
132
  return result;
133
}
134
 
135
static _fpos_t
136
_DEFUN(funseeker, (ptr, cookie, off, whence),
137
       struct _reent *ptr _AND
138
       void *cookie _AND
139
       _fpos_t off _AND
140
       int whence)
141
{
142
  funcookie *c = (funcookie *) cookie;
143
#ifndef __LARGE64_FILES
144
  fpos_t result;
145
  errno = 0;
146
  if ((result = c->seekfn (c->cookie, (fpos_t) off, whence)) < 0 && errno)
147
    ptr->_errno = errno;
148
#else /* __LARGE64_FILES */
149
  _fpos64_t result;
150
  errno = 0;
151
  if ((result = c->seekfn (c->cookie, (_fpos64_t) off, whence)) < 0 && errno)
152
    ptr->_errno = errno;
153
  else if ((_fpos_t)result != result)
154
    {
155
      ptr->_errno = EOVERFLOW;
156
      result = -1;
157
    }
158
#endif /* __LARGE64_FILES */
159
  return result;
160
}
161
 
162
#ifdef __LARGE64_FILES
163
static _fpos64_t
164
_DEFUN(funseeker64, (ptr, cookie, off, whence),
165
       struct _reent *ptr _AND
166
       void *cookie _AND
167
       _fpos64_t off _AND
168
       int whence)
169
{
170
  _fpos64_t result;
171
  funcookie *c = (funcookie *) cookie;
172
  errno = 0;
173
  if ((result = c->seekfn (c->cookie, off, whence)) < 0 && errno)
174
    ptr->_errno = errno;
175
  return result;
176
}
177
#endif /* __LARGE64_FILES */
178
 
179
static int
180
_DEFUN(funcloser, (ptr, cookie),
181
       struct _reent *ptr _AND
182
       void *cookie)
183
{
184
  int result = 0;
185
  funcookie *c = (funcookie *) cookie;
186
  if (c->closefn)
187
    {
188
      errno = 0;
189
      if ((result = c->closefn (c->cookie)) < 0 && errno)
190
        ptr->_errno = errno;
191
    }
192
  _free_r (ptr, c);
193
  return result;
194
}
195
 
196
FILE *
197
_DEFUN(_funopen_r, (ptr, cookie, readfn, writefn, seekfn, closefn),
198
       struct _reent *ptr _AND
199
       const void *cookie _AND
200
       funread readfn _AND
201
       funwrite writefn _AND
202
       funseek seekfn _AND
203
       funclose closefn)
204
{
205
  FILE *fp;
206
  funcookie *c;
207
 
208
  if (!readfn && !writefn)
209
    {
210
      ptr->_errno = EINVAL;
211
      return NULL;
212
    }
213
  if ((fp = __sfp (ptr)) == NULL)
214
    return NULL;
215
  if ((c = (funcookie *) _malloc_r (ptr, sizeof *c)) == NULL)
216
    {
217
      __sfp_lock_acquire ();
218
      fp->_flags = 0;            /* release */
219
#ifndef __SINGLE_THREAD__
220
      __lock_close_recursive (fp->_lock);
221
#endif
222
      __sfp_lock_release ();
223
      return NULL;
224
    }
225
 
226
  _flockfile (fp);
227
  fp->_file = -1;
228
  c->cookie = (void *) cookie; /* cast away const */
229
  fp->_cookie = c;
230
  if (readfn)
231
    {
232
      c->readfn = readfn;
233
      fp->_read = funreader;
234
      if (writefn)
235
        {
236
          fp->_flags = __SRW;
237
          c->writefn = writefn;
238
          fp->_write = funwriter;
239
        }
240
      else
241
        {
242
          fp->_flags = __SRD;
243
          c->writefn = NULL;
244
          fp->_write = NULL;
245
        }
246
    }
247
  else
248
    {
249
      fp->_flags = __SWR;
250
      c->writefn = writefn;
251
      fp->_write = funwriter;
252
      c->readfn = NULL;
253
      fp->_read = NULL;
254
    }
255
  c->seekfn = seekfn;
256
  fp->_seek = seekfn ? funseeker : NULL;
257
#ifdef __LARGE64_FILES
258
  fp->_seek64 = seekfn ? funseeker64 : NULL;
259
  fp->_flags |= __SL64;
260
#endif
261
  c->closefn = closefn;
262
  fp->_close = funcloser;
263
  _funlockfile (fp);
264
  return fp;
265
}
266
 
267
#ifndef _REENT_ONLY
268
FILE *
269
_DEFUN(funopen, (cookie, readfn, writefn, seekfn, closefn),
270
       const void *cookie _AND
271
       funread readfn _AND
272
       funwrite writefn _AND
273
       funseek seekfn _AND
274
       funclose closefn)
275
{
276
  return _funopen_r (_REENT, cookie, readfn, writefn, seekfn, closefn);
277
}
278
#endif /* !_REENT_ONLY */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.