OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [newlib-1.18.0/] [newlib-1.18.0-or32-1.0rc1/] [newlib/] [libc/] [stdio/] [fopencookie.c] - Diff between revs 207 and 345

Only display areas with differences | Details | Blame | View Log

Rev 207 Rev 345
/* Copyright (C) 2007 Eric Blake
/* Copyright (C) 2007 Eric Blake
 * Permission to use, copy, modify, and distribute this software
 * Permission to use, copy, modify, and distribute this software
 * is freely granted, provided that this notice is preserved.
 * is freely granted, provided that this notice is preserved.
 */
 */
 
 
/*
/*
FUNCTION
FUNCTION
<<fopencookie>>---open a stream with custom callbacks
<<fopencookie>>---open a stream with custom callbacks
 
 
INDEX
INDEX
        fopencookie
        fopencookie
 
 
ANSI_SYNOPSIS
ANSI_SYNOPSIS
        #include <stdio.h>
        #include <stdio.h>
        FILE *fopencookie(const void *<[cookie]>, const char *<[mode]>,
        FILE *fopencookie(const void *<[cookie]>, const char *<[mode]>,
                          cookie_io_functions_t <[functions]>);
                          cookie_io_functions_t <[functions]>);
 
 
DESCRIPTION
DESCRIPTION
<<fopencookie>> creates a <<FILE>> stream where I/O is performed using
<<fopencookie>> creates a <<FILE>> stream where I/O is performed using
custom callbacks.  The callbacks are registered via the structure:
custom callbacks.  The callbacks are registered via the structure:
 
 
        typedef ssize_t (*cookie_read_function_t)(void *_cookie, char *_buf,
        typedef ssize_t (*cookie_read_function_t)(void *_cookie, char *_buf,
                                                  size_t _n);
                                                  size_t _n);
        typedef ssize_t (*cookie_write_function_t)(void *_cookie,
        typedef ssize_t (*cookie_write_function_t)(void *_cookie,
                                                   const char *_buf, size_t _n);
                                                   const char *_buf, size_t _n);
        typedef int (*cookie_seek_function_t)(void *_cookie, off_t *_off,
        typedef int (*cookie_seek_function_t)(void *_cookie, off_t *_off,
                                              int _whence);
                                              int _whence);
        typedef int (*cookie_close_function_t)(void *_cookie);
        typedef int (*cookie_close_function_t)(void *_cookie);
 
 
.       typedef struct
.       typedef struct
.       {
.       {
.               cookie_read_function_t  *read;
.               cookie_read_function_t  *read;
.               cookie_write_function_t *write;
.               cookie_write_function_t *write;
.               cookie_seek_function_t  *seek;
.               cookie_seek_function_t  *seek;
.               cookie_close_function_t *close;
.               cookie_close_function_t *close;
.       } cookie_io_functions_t;
.       } cookie_io_functions_t;
 
 
The stream is opened with <[mode]> treated as in <<fopen>>.  The
The stream is opened with <[mode]> treated as in <<fopen>>.  The
callbacks <[functions.read]> and <[functions.write]> may only be NULL
callbacks <[functions.read]> and <[functions.write]> may only be NULL
when <[mode]> does not require them.
when <[mode]> does not require them.
 
 
<[functions.read]> should return -1 on failure, or else the number of
<[functions.read]> should return -1 on failure, or else the number of
bytes read (0 on EOF).  It is similar to <<read>>, except that
bytes read (0 on EOF).  It is similar to <<read>>, except that
<[cookie]> will be passed as the first argument.
<[cookie]> will be passed as the first argument.
 
 
<[functions.write]> should return -1 on failure, or else the number of
<[functions.write]> should return -1 on failure, or else the number of
bytes written.  It is similar to <<write>>, except that <[cookie]>
bytes written.  It is similar to <<write>>, except that <[cookie]>
will be passed as the first argument.
will be passed as the first argument.
 
 
<[functions.seek]> should return -1 on failure, and 0 on success, with
<[functions.seek]> should return -1 on failure, and 0 on success, with
*<[_off]> set to the current file position.  It is a cross between
*<[_off]> set to the current file position.  It is a cross between
<<lseek>> and <<fseek>>, with the <[_whence]> argument interpreted in
<<lseek>> and <<fseek>>, with the <[_whence]> argument interpreted in
the same manner.  A NULL <[functions.seek]> makes the stream behave
the same manner.  A NULL <[functions.seek]> makes the stream behave
similarly to a pipe in relation to stdio functions that require
similarly to a pipe in relation to stdio functions that require
positioning.
positioning.
 
 
<[functions.close]> should return -1 on failure, or 0 on success.  It
<[functions.close]> should return -1 on failure, or 0 on success.  It
is similar to <<close>>, except that <[cookie]> will be passed as the
is similar to <<close>>, except that <[cookie]> will be passed as the
first argument.  A NULL <[functions.close]> merely flushes all data
first argument.  A NULL <[functions.close]> merely flushes all data
then lets <<fclose>> succeed.  A failed close will still invalidate
then lets <<fclose>> succeed.  A failed close will still invalidate
the stream.
the stream.
 
 
Read and write I/O functions are allowed to change the underlying
Read and write I/O functions are allowed to change the underlying
buffer on fully buffered or line buffered streams by calling
buffer on fully buffered or line buffered streams by calling
<<setvbuf>>.  They are also not required to completely fill or empty
<<setvbuf>>.  They are also not required to completely fill or empty
the buffer.  They are not, however, allowed to change streams from
the buffer.  They are not, however, allowed to change streams from
unbuffered to buffered or to change the state of the line buffering
unbuffered to buffered or to change the state of the line buffering
flag.  They must also be prepared to have read or write calls occur on
flag.  They must also be prepared to have read or write calls occur on
buffers other than the one most recently specified.
buffers other than the one most recently specified.
 
 
RETURNS
RETURNS
The return value is an open FILE pointer on success.  On error,
The return value is an open FILE pointer on success.  On error,
<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
<<NULL>> is returned, and <<errno>> will be set to EINVAL if a
function pointer is missing or <[mode]> is invalid, ENOMEM if the
function pointer is missing or <[mode]> is invalid, ENOMEM if the
stream cannot be created, or EMFILE if too many streams are already
stream cannot be created, or EMFILE if too many streams are already
open.
open.
 
 
PORTABILITY
PORTABILITY
This function is a newlib extension, copying the prototype from Linux.
This function is a newlib extension, copying the prototype from Linux.
It is not portable.  See also the <<funopen>> interface from BSD.
It is not portable.  See also the <<funopen>> interface from BSD.
 
 
Supporting OS subroutines required: <<sbrk>>.
Supporting OS subroutines required: <<sbrk>>.
*/
*/
 
 
#include <stdio.h>
#include <stdio.h>
#include <errno.h>
#include <errno.h>
#include <sys/lock.h>
#include <sys/lock.h>
#include "local.h"
#include "local.h"
 
 
typedef struct fccookie {
typedef struct fccookie {
  void *cookie;
  void *cookie;
  FILE *fp;
  FILE *fp;
  cookie_read_function_t *readfn;
  cookie_read_function_t *readfn;
  cookie_write_function_t *writefn;
  cookie_write_function_t *writefn;
  cookie_seek_function_t *seekfn;
  cookie_seek_function_t *seekfn;
  cookie_close_function_t *closefn;
  cookie_close_function_t *closefn;
} fccookie;
} fccookie;
 
 
static _READ_WRITE_RETURN_TYPE
static _READ_WRITE_RETURN_TYPE
_DEFUN(fcreader, (ptr, cookie, buf, n),
_DEFUN(fcreader, (ptr, cookie, buf, n),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie _AND
       void *cookie _AND
       char *buf _AND
       char *buf _AND
       int n)
       int n)
{
{
  int result;
  int result;
  fccookie *c = (fccookie *) cookie;
  fccookie *c = (fccookie *) cookie;
  errno = 0;
  errno = 0;
  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
  if ((result = c->readfn (c->cookie, buf, n)) < 0 && errno)
    ptr->_errno = errno;
    ptr->_errno = errno;
  return result;
  return result;
}
}
 
 
static _READ_WRITE_RETURN_TYPE
static _READ_WRITE_RETURN_TYPE
_DEFUN(fcwriter, (ptr, cookie, buf, n),
_DEFUN(fcwriter, (ptr, cookie, buf, n),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie _AND
       void *cookie _AND
       const char *buf _AND
       const char *buf _AND
       int n)
       int n)
{
{
  int result;
  int result;
  fccookie *c = (fccookie *) cookie;
  fccookie *c = (fccookie *) cookie;
  if (c->fp->_flags & __SAPP && c->fp->_seek)
  if (c->fp->_flags & __SAPP && c->fp->_seek)
    {
    {
#ifdef __LARGE64_FILES
#ifdef __LARGE64_FILES
      c->fp->_seek64 (ptr, cookie, 0, SEEK_END);
      c->fp->_seek64 (ptr, cookie, 0, SEEK_END);
#else
#else
      c->fp->_seek (ptr, cookie, 0, SEEK_END);
      c->fp->_seek (ptr, cookie, 0, SEEK_END);
#endif
#endif
    }
    }
  errno = 0;
  errno = 0;
  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
  if ((result = c->writefn (c->cookie, buf, n)) < 0 && errno)
    ptr->_errno = errno;
    ptr->_errno = errno;
  return result;
  return result;
}
}
 
 
static _fpos_t
static _fpos_t
_DEFUN(fcseeker, (ptr, cookie, pos, whence),
_DEFUN(fcseeker, (ptr, cookie, pos, whence),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie _AND
       void *cookie _AND
       _fpos_t pos _AND
       _fpos_t pos _AND
       int whence)
       int whence)
{
{
  fccookie *c = (fccookie *) cookie;
  fccookie *c = (fccookie *) cookie;
#ifndef __LARGE64_FILES
#ifndef __LARGE64_FILES
  off_t offset = (off_t) pos;
  off_t offset = (off_t) pos;
#else /* __LARGE64_FILES */
#else /* __LARGE64_FILES */
  _off64_t offset = (_off64_t) pos;
  _off64_t offset = (_off64_t) pos;
#endif /* __LARGE64_FILES */
#endif /* __LARGE64_FILES */
 
 
  errno = 0;
  errno = 0;
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
    ptr->_errno = errno;
    ptr->_errno = errno;
#ifdef __LARGE64_FILES
#ifdef __LARGE64_FILES
  else if ((_fpos_t)offset != offset)
  else if ((_fpos_t)offset != offset)
    {
    {
      ptr->_errno = EOVERFLOW;
      ptr->_errno = EOVERFLOW;
      offset = -1;
      offset = -1;
    }
    }
#endif /* __LARGE64_FILES */
#endif /* __LARGE64_FILES */
  return (_fpos_t) offset;
  return (_fpos_t) offset;
}
}
 
 
#ifdef __LARGE64_FILES
#ifdef __LARGE64_FILES
static _fpos64_t
static _fpos64_t
_DEFUN(fcseeker64, (ptr, cookie, pos, whence),
_DEFUN(fcseeker64, (ptr, cookie, pos, whence),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie _AND
       void *cookie _AND
       _fpos64_t pos _AND
       _fpos64_t pos _AND
       int whence)
       int whence)
{
{
  _off64_t offset;
  _off64_t offset;
  fccookie *c = (fccookie *) cookie;
  fccookie *c = (fccookie *) cookie;
  errno = 0;
  errno = 0;
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
  if (c->seekfn (c->cookie, &offset, whence) < 0 && errno)
    ptr->_errno = errno;
    ptr->_errno = errno;
  return (_fpos64_t) offset;
  return (_fpos64_t) offset;
}
}
#endif /* __LARGE64_FILES */
#endif /* __LARGE64_FILES */
 
 
static int
static int
_DEFUN(fccloser, (ptr, cookie),
_DEFUN(fccloser, (ptr, cookie),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie)
       void *cookie)
{
{
  int result = 0;
  int result = 0;
  fccookie *c = (fccookie *) cookie;
  fccookie *c = (fccookie *) cookie;
  if (c->closefn)
  if (c->closefn)
    {
    {
      errno = 0;
      errno = 0;
      if ((result = c->closefn (c->cookie)) < 0 && errno)
      if ((result = c->closefn (c->cookie)) < 0 && errno)
        ptr->_errno = errno;
        ptr->_errno = errno;
    }
    }
  _free_r (ptr, c);
  _free_r (ptr, c);
  return result;
  return result;
}
}
 
 
FILE *
FILE *
_DEFUN(_fopencookie_r, (ptr, cookie, mode, functions),
_DEFUN(_fopencookie_r, (ptr, cookie, mode, functions),
       struct _reent *ptr _AND
       struct _reent *ptr _AND
       void *cookie _AND
       void *cookie _AND
       const char *mode _AND
       const char *mode _AND
       cookie_io_functions_t functions)
       cookie_io_functions_t functions)
{
{
  FILE *fp;
  FILE *fp;
  fccookie *c;
  fccookie *c;
  int flags;
  int flags;
  int dummy;
  int dummy;
 
 
  if ((flags = __sflags (ptr, mode, &dummy)) == 0)
  if ((flags = __sflags (ptr, mode, &dummy)) == 0)
    return NULL;
    return NULL;
  if (((flags & (__SRD | __SRW)) && !functions.read)
  if (((flags & (__SRD | __SRW)) && !functions.read)
      || ((flags & (__SWR | __SRW)) && !functions.write))
      || ((flags & (__SWR | __SRW)) && !functions.write))
    {
    {
      ptr->_errno = EINVAL;
      ptr->_errno = EINVAL;
      return NULL;
      return NULL;
    }
    }
  if ((fp = __sfp (ptr)) == NULL)
  if ((fp = __sfp (ptr)) == NULL)
    return NULL;
    return NULL;
  if ((c = (fccookie *) _malloc_r (ptr, sizeof *c)) == NULL)
  if ((c = (fccookie *) _malloc_r (ptr, sizeof *c)) == NULL)
    {
    {
      __sfp_lock_acquire ();
      __sfp_lock_acquire ();
      fp->_flags = 0;            /* release */
      fp->_flags = 0;            /* release */
#ifndef __SINGLE_THREAD__
#ifndef __SINGLE_THREAD__
      __lock_close_recursive (fp->_lock);
      __lock_close_recursive (fp->_lock);
#endif
#endif
      __sfp_lock_release ();
      __sfp_lock_release ();
      return NULL;
      return NULL;
    }
    }
 
 
  _flockfile (fp);
  _flockfile (fp);
  fp->_file = -1;
  fp->_file = -1;
  fp->_flags = flags;
  fp->_flags = flags;
  c->cookie = cookie;
  c->cookie = cookie;
  c->fp = fp;
  c->fp = fp;
  fp->_cookie = c;
  fp->_cookie = c;
  c->readfn = functions.read;
  c->readfn = functions.read;
  fp->_read = fcreader;
  fp->_read = fcreader;
  c->writefn = functions.write;
  c->writefn = functions.write;
  fp->_write = fcwriter;
  fp->_write = fcwriter;
  c->seekfn = functions.seek;
  c->seekfn = functions.seek;
  fp->_seek = functions.seek ? fcseeker : NULL;
  fp->_seek = functions.seek ? fcseeker : NULL;
#ifdef __LARGE64_FILES
#ifdef __LARGE64_FILES
  fp->_seek64 = functions.seek ? fcseeker64 : NULL;
  fp->_seek64 = functions.seek ? fcseeker64 : NULL;
  fp->_flags |= __SL64;
  fp->_flags |= __SL64;
#endif
#endif
  c->closefn = functions.close;
  c->closefn = functions.close;
  fp->_close = fccloser;
  fp->_close = fccloser;
  _funlockfile (fp);
  _funlockfile (fp);
  return fp;
  return fp;
}
}
 
 
#ifndef _REENT_ONLY
#ifndef _REENT_ONLY
FILE *
FILE *
_DEFUN(fopencookie, (cookie, mode, functions),
_DEFUN(fopencookie, (cookie, mode, functions),
       void *cookie _AND
       void *cookie _AND
       const char *mode _AND
       const char *mode _AND
       cookie_io_functions_t functions)
       cookie_io_functions_t functions)
{
{
  return _fopencookie_r (_REENT, cookie, mode, functions);
  return _fopencookie_r (_REENT, cookie, mode, functions);
}
}
#endif /* !_REENT_ONLY */
#endif /* !_REENT_ONLY */
 
 

powered by: WebSVN 2.1.0

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