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/] [gdb-6.8/] [pre-binutils-2.20.1-sync/] [sim/] [common/] [callback.c] - Diff between revs 157 and 223

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 157 Rev 223
/* Remote target callback routines.
/* Remote target callback routines.
   Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2004, 2007, 2008
   Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2004, 2007, 2008
   Free Software Foundation, Inc.
   Free Software Foundation, Inc.
   Contributed by Cygnus Solutions.
   Contributed by Cygnus Solutions.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   This program is free software; you can redistribute it and/or modify
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3 of the License, or
   the Free Software Foundation; either version 3 of the License, or
   (at your option) any later version.
   (at your option) any later version.
 
 
   This program is distributed in the hope that it will be useful,
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   GNU General Public License for more details.
 
 
   You should have received a copy of the GNU General Public License
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 
/* This file provides a standard way for targets to talk to the host OS
/* This file provides a standard way for targets to talk to the host OS
   level.  */
   level.  */
 
 
#ifdef HAVE_CONFIG_H
#ifdef HAVE_CONFIG_H
#include "cconfig.h"
#include "cconfig.h"
#endif
#endif
#include "ansidecl.h"
#include "ansidecl.h"
#include <stdarg.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdio.h>
#ifdef HAVE_STDLIB_H
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#include <stdlib.h>
#endif
#endif
#ifdef HAVE_STRING_H
#ifdef HAVE_STRING_H
#include <string.h>
#include <string.h>
#else
#else
#ifdef HAVE_STRINGS_H
#ifdef HAVE_STRINGS_H
#include <strings.h>
#include <strings.h>
#endif
#endif
#endif
#endif
#ifdef HAVE_LIMITS_H
#ifdef HAVE_LIMITS_H
/* For PIPE_BUF.  */
/* For PIPE_BUF.  */
#include <limits.h>
#include <limits.h>
#endif
#endif
#include <errno.h>
#include <errno.h>
#include <fcntl.h>
#include <fcntl.h>
#include <time.h>
#include <time.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include "gdb/callback.h"
#include "gdb/callback.h"
#include "targ-vals.h"
#include "targ-vals.h"
/* For xmalloc.  */
/* For xmalloc.  */
#include "libiberty.h"
#include "libiberty.h"
 
 
#ifdef HAVE_UNISTD_H
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#include <unistd.h>
#endif
#endif
 
 
#ifndef PIPE_BUF
#ifndef PIPE_BUF
#define PIPE_BUF 512
#define PIPE_BUF 512
#endif
#endif
 
 
/* ??? sim_cb_printf should be cb_printf, but until the callback support is
/* ??? sim_cb_printf should be cb_printf, but until the callback support is
   broken out of the simulator directory, these are here to not require
   broken out of the simulator directory, these are here to not require
   sim-utils.h.  */
   sim-utils.h.  */
void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
 
 
extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
extern CB_TARGET_DEFS_MAP cb_init_open_map[];
extern CB_TARGET_DEFS_MAP cb_init_open_map[];
 
 
extern int system PARAMS ((const char *));
extern int system PARAMS ((const char *));
 
 
static int os_init PARAMS ((host_callback *));
static int os_init PARAMS ((host_callback *));
static int os_shutdown PARAMS ((host_callback *));
static int os_shutdown PARAMS ((host_callback *));
static int os_unlink PARAMS ((host_callback *, const char *));
static int os_unlink PARAMS ((host_callback *, const char *));
static long os_time PARAMS ((host_callback *, long *));
static long os_time PARAMS ((host_callback *, long *));
static int os_system PARAMS ((host_callback *, const char *));
static int os_system PARAMS ((host_callback *, const char *));
static int os_rename PARAMS ((host_callback *, const char *, const char *));
static int os_rename PARAMS ((host_callback *, const char *, const char *));
static int os_write_stdout PARAMS ((host_callback *, const char *, int));
static int os_write_stdout PARAMS ((host_callback *, const char *, int));
static void os_flush_stdout PARAMS ((host_callback *));
static void os_flush_stdout PARAMS ((host_callback *));
static int os_write_stderr PARAMS ((host_callback *, const char *, int));
static int os_write_stderr PARAMS ((host_callback *, const char *, int));
static void os_flush_stderr PARAMS ((host_callback *));
static void os_flush_stderr PARAMS ((host_callback *));
static int os_write PARAMS ((host_callback *, int, const char *, int));
static int os_write PARAMS ((host_callback *, int, const char *, int));
static int os_read_stdin PARAMS ((host_callback *, char *, int));
static int os_read_stdin PARAMS ((host_callback *, char *, int));
static int os_read PARAMS ((host_callback *, int, char *, int));
static int os_read PARAMS ((host_callback *, int, char *, int));
static int os_open PARAMS ((host_callback *, const char *, int));
static int os_open PARAMS ((host_callback *, const char *, int));
static int os_lseek PARAMS ((host_callback *, int, long, int));
static int os_lseek PARAMS ((host_callback *, int, long, int));
static int os_isatty PARAMS ((host_callback *, int));
static int os_isatty PARAMS ((host_callback *, int));
static int os_get_errno PARAMS ((host_callback *));
static int os_get_errno PARAMS ((host_callback *));
static int os_close PARAMS ((host_callback *, int));
static int os_close PARAMS ((host_callback *, int));
static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
static void os_error PARAMS ((host_callback *, const char *, ...));
static void os_error PARAMS ((host_callback *, const char *, ...));
static int fdmap PARAMS ((host_callback *, int));
static int fdmap PARAMS ((host_callback *, int));
static int fdbad PARAMS ((host_callback *, int));
static int fdbad PARAMS ((host_callback *, int));
static int wrap PARAMS ((host_callback *, int));
static int wrap PARAMS ((host_callback *, int));
 
 
/* Set the callback copy of errno from what we see now.  */
/* Set the callback copy of errno from what we see now.  */
 
 
static int
static int
wrap (p, val)
wrap (p, val)
     host_callback *p;
     host_callback *p;
     int val;
     int val;
{
{
  p->last_errno = errno;
  p->last_errno = errno;
  return val;
  return val;
}
}
 
 
/* Make sure the FD provided is ok.  If not, return non-zero
/* Make sure the FD provided is ok.  If not, return non-zero
   and set errno. */
   and set errno. */
 
 
static int
static int
fdbad (p, fd)
fdbad (p, fd)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
{
{
  if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
  if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
    {
    {
      p->last_errno = EINVAL;
      p->last_errno = EINVAL;
      return -1;
      return -1;
    }
    }
  return 0;
  return 0;
}
}
 
 
static int
static int
fdmap (p, fd)
fdmap (p, fd)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
{
{
  return p->fdmap[fd];
  return p->fdmap[fd];
}
}
 
 
static int
static int
os_close (p, fd)
os_close (p, fd)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
{
{
  int result;
  int result;
  int i, next;
  int i, next;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (result)
  if (result)
    return result;
    return result;
  /* If this file descripter has one or more buddies (originals /
  /* If this file descripter has one or more buddies (originals /
     duplicates from a dup), just remove it from the circular list.  */
     duplicates from a dup), just remove it from the circular list.  */
  for (i = fd; (next = p->fd_buddy[i]) != fd; )
  for (i = fd; (next = p->fd_buddy[i]) != fd; )
    i = next;
    i = next;
  if (fd != i)
  if (fd != i)
    p->fd_buddy[i] = p->fd_buddy[fd];
    p->fd_buddy[i] = p->fd_buddy[fd];
  else
  else
    {
    {
      if (p->ispipe[fd])
      if (p->ispipe[fd])
        {
        {
          int other = p->ispipe[fd];
          int other = p->ispipe[fd];
          int reader, writer;
          int reader, writer;
 
 
          if (other > 0)
          if (other > 0)
            {
            {
              /* Closing the read side.  */
              /* Closing the read side.  */
              reader = fd;
              reader = fd;
              writer = other;
              writer = other;
            }
            }
          else
          else
            {
            {
              /* Closing the write side.  */
              /* Closing the write side.  */
              writer = fd;
              writer = fd;
              reader = -other;
              reader = -other;
            }
            }
 
 
          /* If there was data in the buffer, make a last "now empty"
          /* If there was data in the buffer, make a last "now empty"
             call, then deallocate data.  */
             call, then deallocate data.  */
          if (p->pipe_buffer[writer].buffer != NULL)
          if (p->pipe_buffer[writer].buffer != NULL)
            {
            {
              (*p->pipe_empty) (p, reader, writer);
              (*p->pipe_empty) (p, reader, writer);
              free (p->pipe_buffer[writer].buffer);
              free (p->pipe_buffer[writer].buffer);
              p->pipe_buffer[writer].buffer = NULL;
              p->pipe_buffer[writer].buffer = NULL;
            }
            }
 
 
          /* Clear pipe data for this side.  */
          /* Clear pipe data for this side.  */
          p->pipe_buffer[fd].size = 0;
          p->pipe_buffer[fd].size = 0;
          p->ispipe[fd] = 0;
          p->ispipe[fd] = 0;
 
 
          /* If this was the first close, mark the other side as the
          /* If this was the first close, mark the other side as the
             only remaining side.  */
             only remaining side.  */
          if (fd != abs (other))
          if (fd != abs (other))
            p->ispipe[abs (other)] = -other;
            p->ispipe[abs (other)] = -other;
          p->fd_buddy[fd] = -1;
          p->fd_buddy[fd] = -1;
          return 0;
          return 0;
        }
        }
 
 
      result = wrap (p, close (fdmap (p, fd)));
      result = wrap (p, close (fdmap (p, fd)));
    }
    }
  p->fd_buddy[fd] = -1;
  p->fd_buddy[fd] = -1;
 
 
  return result;
  return result;
}
}
 
 
 
 
/* taken from gdb/util.c:notice_quit() - should be in a library */
/* taken from gdb/util.c:notice_quit() - should be in a library */
 
 
 
 
#if defined(__GO32__) || defined (_MSC_VER)
#if defined(__GO32__) || defined (_MSC_VER)
static int
static int
os_poll_quit (p)
os_poll_quit (p)
     host_callback *p;
     host_callback *p;
{
{
#if defined(__GO32__)
#if defined(__GO32__)
  int kbhit ();
  int kbhit ();
  int getkey ();
  int getkey ();
  if (kbhit ())
  if (kbhit ())
    {
    {
      int k = getkey ();
      int k = getkey ();
      if (k == 1)
      if (k == 1)
        {
        {
          return 1;
          return 1;
        }
        }
      else if (k == 2)
      else if (k == 2)
        {
        {
          return 1;
          return 1;
        }
        }
      else
      else
        {
        {
          sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
          sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
        }
        }
    }
    }
#endif
#endif
#if defined (_MSC_VER)
#if defined (_MSC_VER)
  /* NB - this will not compile! */
  /* NB - this will not compile! */
  int k = win32pollquit();
  int k = win32pollquit();
  if (k == 1)
  if (k == 1)
    return 1;
    return 1;
  else if (k == 2)
  else if (k == 2)
    return 1;
    return 1;
#endif
#endif
  return 0;
  return 0;
}
}
#else
#else
#define os_poll_quit 0
#define os_poll_quit 0
#endif /* defined(__GO32__) || defined(_MSC_VER) */
#endif /* defined(__GO32__) || defined(_MSC_VER) */
 
 
static int
static int
os_get_errno (p)
os_get_errno (p)
     host_callback *p;
     host_callback *p;
{
{
  return cb_host_to_target_errno (p, p->last_errno);
  return cb_host_to_target_errno (p, p->last_errno);
}
}
 
 
 
 
static int
static int
os_isatty (p, fd)
os_isatty (p, fd)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
{
{
  int result;
  int result;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (result)
  if (result)
    return result;
    return result;
  result = wrap (p, isatty (fdmap (p, fd)));
  result = wrap (p, isatty (fdmap (p, fd)));
 
 
  return result;
  return result;
}
}
 
 
static int
static int
os_lseek (p, fd, off, way)
os_lseek (p, fd, off, way)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
     long off;
     long off;
     int way;
     int way;
{
{
  int result;
  int result;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (result)
  if (result)
    return result;
    return result;
  result = lseek (fdmap (p, fd), off, way);
  result = lseek (fdmap (p, fd), off, way);
  return result;
  return result;
}
}
 
 
static int
static int
os_open (p, name, flags)
os_open (p, name, flags)
     host_callback *p;
     host_callback *p;
     const char *name;
     const char *name;
     int flags;
     int flags;
{
{
  int i;
  int i;
  for (i = 0; i < MAX_CALLBACK_FDS; i++)
  for (i = 0; i < MAX_CALLBACK_FDS; i++)
    {
    {
      if (p->fd_buddy[i] < 0)
      if (p->fd_buddy[i] < 0)
        {
        {
          int f = open (name, cb_target_to_host_open (p, flags), 0644);
          int f = open (name, cb_target_to_host_open (p, flags), 0644);
          if (f < 0)
          if (f < 0)
            {
            {
              p->last_errno = errno;
              p->last_errno = errno;
              return f;
              return f;
            }
            }
          p->fd_buddy[i] = i;
          p->fd_buddy[i] = i;
          p->fdmap[i] = f;
          p->fdmap[i] = f;
          return i;
          return i;
        }
        }
    }
    }
  p->last_errno = EMFILE;
  p->last_errno = EMFILE;
  return -1;
  return -1;
}
}
 
 
static int
static int
os_read (p, fd, buf, len)
os_read (p, fd, buf, len)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
     char *buf;
     char *buf;
     int len;
     int len;
{
{
  int result;
  int result;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (result)
  if (result)
    return result;
    return result;
  if (p->ispipe[fd])
  if (p->ispipe[fd])
    {
    {
      int writer = p->ispipe[fd];
      int writer = p->ispipe[fd];
 
 
      /* Can't read from the write-end.  */
      /* Can't read from the write-end.  */
      if (writer < 0)
      if (writer < 0)
        {
        {
          p->last_errno = EBADF;
          p->last_errno = EBADF;
          return -1;
          return -1;
        }
        }
 
 
      /* Nothing to read if nothing is written.  */
      /* Nothing to read if nothing is written.  */
      if (p->pipe_buffer[writer].size == 0)
      if (p->pipe_buffer[writer].size == 0)
        return 0;
        return 0;
 
 
      /* Truncate read request size to buffer size minus what's already
      /* Truncate read request size to buffer size minus what's already
         read.  */
         read.  */
      if (len > p->pipe_buffer[writer].size - p->pipe_buffer[fd].size)
      if (len > p->pipe_buffer[writer].size - p->pipe_buffer[fd].size)
        len = p->pipe_buffer[writer].size - p->pipe_buffer[fd].size;
        len = p->pipe_buffer[writer].size - p->pipe_buffer[fd].size;
 
 
      memcpy (buf, p->pipe_buffer[writer].buffer + p->pipe_buffer[fd].size,
      memcpy (buf, p->pipe_buffer[writer].buffer + p->pipe_buffer[fd].size,
              len);
              len);
 
 
      /* Account for what we just read.  */
      /* Account for what we just read.  */
      p->pipe_buffer[fd].size += len;
      p->pipe_buffer[fd].size += len;
 
 
      /* If we've read everything, empty and deallocate the buffer and
      /* If we've read everything, empty and deallocate the buffer and
         signal buffer-empty to client.  (This isn't expected to be a
         signal buffer-empty to client.  (This isn't expected to be a
         hot path in the simulator, so we don't hold on to the buffer.)  */
         hot path in the simulator, so we don't hold on to the buffer.)  */
      if (p->pipe_buffer[fd].size == p->pipe_buffer[writer].size)
      if (p->pipe_buffer[fd].size == p->pipe_buffer[writer].size)
        {
        {
          free (p->pipe_buffer[writer].buffer);
          free (p->pipe_buffer[writer].buffer);
          p->pipe_buffer[writer].buffer = NULL;
          p->pipe_buffer[writer].buffer = NULL;
          p->pipe_buffer[fd].size = 0;
          p->pipe_buffer[fd].size = 0;
          p->pipe_buffer[writer].size = 0;
          p->pipe_buffer[writer].size = 0;
          (*p->pipe_empty) (p, fd, writer);
          (*p->pipe_empty) (p, fd, writer);
        }
        }
 
 
      return len;
      return len;
    }
    }
 
 
  result = wrap (p, read (fdmap (p, fd), buf, len));
  result = wrap (p, read (fdmap (p, fd), buf, len));
  return result;
  return result;
}
}
 
 
static int
static int
os_read_stdin (p, buf, len)
os_read_stdin (p, buf, len)
     host_callback *p;
     host_callback *p;
     char *buf;
     char *buf;
     int len;
     int len;
{
{
  return wrap (p, read (0, buf, len));
  return wrap (p, read (0, buf, len));
}
}
 
 
static int
static int
os_write (p, fd, buf, len)
os_write (p, fd, buf, len)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
     const char *buf;
     const char *buf;
     int len;
     int len;
{
{
  int result;
  int result;
  int real_fd;
  int real_fd;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (result)
  if (result)
    return result;
    return result;
 
 
  if (p->ispipe[fd])
  if (p->ispipe[fd])
    {
    {
      int reader = -p->ispipe[fd];
      int reader = -p->ispipe[fd];
 
 
      /* Can't write to the read-end.  */
      /* Can't write to the read-end.  */
      if (reader < 0)
      if (reader < 0)
        {
        {
          p->last_errno = EBADF;
          p->last_errno = EBADF;
          return -1;
          return -1;
        }
        }
 
 
      /* Can't write to pipe with closed read end.
      /* Can't write to pipe with closed read end.
         FIXME: We should send a SIGPIPE.  */
         FIXME: We should send a SIGPIPE.  */
      if (reader == fd)
      if (reader == fd)
        {
        {
          p->last_errno = EPIPE;
          p->last_errno = EPIPE;
          return -1;
          return -1;
        }
        }
 
 
      /* As a sanity-check, we bail out it the buffered contents is much
      /* As a sanity-check, we bail out it the buffered contents is much
         larger than the size of the buffer on the host.  We don't want
         larger than the size of the buffer on the host.  We don't want
         to run out of memory in the simulator due to a target program
         to run out of memory in the simulator due to a target program
         bug if we can help it.  Unfortunately, regarding the value that
         bug if we can help it.  Unfortunately, regarding the value that
         reaches the simulated program, it's no use returning *less*
         reaches the simulated program, it's no use returning *less*
         than the requested amount, because cb_syscall loops calling
         than the requested amount, because cb_syscall loops calling
         this function until the whole amount is done.  */
         this function until the whole amount is done.  */
      if (p->pipe_buffer[fd].size + len > 10 * PIPE_BUF)
      if (p->pipe_buffer[fd].size + len > 10 * PIPE_BUF)
        {
        {
          p->last_errno = EFBIG;
          p->last_errno = EFBIG;
          return -1;
          return -1;
        }
        }
 
 
      p->pipe_buffer[fd].buffer
      p->pipe_buffer[fd].buffer
        = xrealloc (p->pipe_buffer[fd].buffer, p->pipe_buffer[fd].size + len);
        = xrealloc (p->pipe_buffer[fd].buffer, p->pipe_buffer[fd].size + len);
      memcpy (p->pipe_buffer[fd].buffer + p->pipe_buffer[fd].size,
      memcpy (p->pipe_buffer[fd].buffer + p->pipe_buffer[fd].size,
              buf, len);
              buf, len);
      p->pipe_buffer[fd].size += len;
      p->pipe_buffer[fd].size += len;
 
 
      (*p->pipe_nonempty) (p, reader, fd);
      (*p->pipe_nonempty) (p, reader, fd);
      return len;
      return len;
    }
    }
 
 
  real_fd = fdmap (p, fd);
  real_fd = fdmap (p, fd);
  switch (real_fd)
  switch (real_fd)
    {
    {
    default:
    default:
      result = wrap (p, write (real_fd, buf, len));
      result = wrap (p, write (real_fd, buf, len));
      break;
      break;
    case 1:
    case 1:
      result = p->write_stdout (p, buf, len);
      result = p->write_stdout (p, buf, len);
      break;
      break;
    case 2:
    case 2:
      result = p->write_stderr (p, buf, len);
      result = p->write_stderr (p, buf, len);
      break;
      break;
    }
    }
  return result;
  return result;
}
}
 
 
static int
static int
os_write_stdout (p, buf, len)
os_write_stdout (p, buf, len)
     host_callback *p ATTRIBUTE_UNUSED;
     host_callback *p ATTRIBUTE_UNUSED;
     const char *buf;
     const char *buf;
     int len;
     int len;
{
{
  return fwrite (buf, 1, len, stdout);
  return fwrite (buf, 1, len, stdout);
}
}
 
 
static void
static void
os_flush_stdout (p)
os_flush_stdout (p)
     host_callback *p ATTRIBUTE_UNUSED;
     host_callback *p ATTRIBUTE_UNUSED;
{
{
  fflush (stdout);
  fflush (stdout);
}
}
 
 
static int
static int
os_write_stderr (p, buf, len)
os_write_stderr (p, buf, len)
     host_callback *p ATTRIBUTE_UNUSED;
     host_callback *p ATTRIBUTE_UNUSED;
     const char *buf;
     const char *buf;
     int len;
     int len;
{
{
  return fwrite (buf, 1, len, stderr);
  return fwrite (buf, 1, len, stderr);
}
}
 
 
static void
static void
os_flush_stderr (p)
os_flush_stderr (p)
     host_callback *p ATTRIBUTE_UNUSED;
     host_callback *p ATTRIBUTE_UNUSED;
{
{
  fflush (stderr);
  fflush (stderr);
}
}
 
 
static int
static int
os_rename (p, f1, f2)
os_rename (p, f1, f2)
     host_callback *p;
     host_callback *p;
     const char *f1;
     const char *f1;
     const char *f2;
     const char *f2;
{
{
  return wrap (p, rename (f1, f2));
  return wrap (p, rename (f1, f2));
}
}
 
 
 
 
static int
static int
os_system (p, s)
os_system (p, s)
     host_callback *p;
     host_callback *p;
     const char *s;
     const char *s;
{
{
  return wrap (p, system (s));
  return wrap (p, system (s));
}
}
 
 
static long
static long
os_time (p, t)
os_time (p, t)
     host_callback *p;
     host_callback *p;
     long *t;
     long *t;
{
{
  return wrap (p, time (t));
  return wrap (p, time (t));
}
}
 
 
 
 
static int
static int
os_unlink (p, f1)
os_unlink (p, f1)
     host_callback *p;
     host_callback *p;
     const char *f1;
     const char *f1;
{
{
  return wrap (p, unlink (f1));
  return wrap (p, unlink (f1));
}
}
 
 
static int
static int
os_stat (p, file, buf)
os_stat (p, file, buf)
     host_callback *p;
     host_callback *p;
     const char *file;
     const char *file;
     struct stat *buf;
     struct stat *buf;
{
{
  /* ??? There is an issue of when to translate to the target layout.
  /* ??? There is an issue of when to translate to the target layout.
     One could do that inside this function, or one could have the
     One could do that inside this function, or one could have the
     caller do it.  It's more flexible to let the caller do it, though
     caller do it.  It's more flexible to let the caller do it, though
     I'm not sure the flexibility will ever be useful.  */
     I'm not sure the flexibility will ever be useful.  */
  return wrap (p, stat (file, buf));
  return wrap (p, stat (file, buf));
}
}
 
 
static int
static int
os_fstat (p, fd, buf)
os_fstat (p, fd, buf)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
     struct stat *buf;
     struct stat *buf;
{
{
  if (fdbad (p, fd))
  if (fdbad (p, fd))
    return -1;
    return -1;
 
 
  if (p->ispipe[fd])
  if (p->ispipe[fd])
    {
    {
#if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME)
#if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME)
      time_t t = (*p->time) (p, NULL);
      time_t t = (*p->time) (p, NULL);
#endif
#endif
 
 
      /* We have to fake the struct stat contents, since the pipe is
      /* We have to fake the struct stat contents, since the pipe is
         made up in the simulator.  */
         made up in the simulator.  */
      memset (buf, 0, sizeof (*buf));
      memset (buf, 0, sizeof (*buf));
 
 
#ifdef HAVE_STRUCT_STAT_ST_MODE
#ifdef HAVE_STRUCT_STAT_ST_MODE
      buf->st_mode = S_IFIFO;
      buf->st_mode = S_IFIFO;
#endif
#endif
 
 
      /* If more accurate tracking than current-time is needed (for
      /* If more accurate tracking than current-time is needed (for
         example, on GNU/Linux we get accurate numbers), the p->time
         example, on GNU/Linux we get accurate numbers), the p->time
         callback (which may be something other than os_time) should
         callback (which may be something other than os_time) should
         happen for each read and write, and we'd need to keep track of
         happen for each read and write, and we'd need to keep track of
         atime, ctime and mtime.  */
         atime, ctime and mtime.  */
#ifdef HAVE_STRUCT_STAT_ST_ATIME
#ifdef HAVE_STRUCT_STAT_ST_ATIME
      buf->st_atime = t;
      buf->st_atime = t;
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIME
#ifdef HAVE_STRUCT_STAT_ST_CTIME
      buf->st_ctime = t;
      buf->st_ctime = t;
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIME
#ifdef HAVE_STRUCT_STAT_ST_MTIME
      buf->st_mtime = t;
      buf->st_mtime = t;
#endif
#endif
      return 0;
      return 0;
    }
    }
 
 
  /* ??? There is an issue of when to translate to the target layout.
  /* ??? There is an issue of when to translate to the target layout.
     One could do that inside this function, or one could have the
     One could do that inside this function, or one could have the
     caller do it.  It's more flexible to let the caller do it, though
     caller do it.  It's more flexible to let the caller do it, though
     I'm not sure the flexibility will ever be useful.  */
     I'm not sure the flexibility will ever be useful.  */
  return wrap (p, fstat (fdmap (p, fd), buf));
  return wrap (p, fstat (fdmap (p, fd), buf));
}
}
 
 
static int
static int
os_lstat (p, file, buf)
os_lstat (p, file, buf)
     host_callback *p;
     host_callback *p;
     const char *file;
     const char *file;
     struct stat *buf;
     struct stat *buf;
{
{
  /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat.  */
  /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat.  */
#ifdef HAVE_LSTAT
#ifdef HAVE_LSTAT
  return wrap (p, lstat (file, buf));
  return wrap (p, lstat (file, buf));
#else
#else
  return wrap (p, stat (file, buf));
  return wrap (p, stat (file, buf));
#endif
#endif
}
}
 
 
static int
static int
os_ftruncate (p, fd, len)
os_ftruncate (p, fd, len)
     host_callback *p;
     host_callback *p;
     int fd;
     int fd;
     long len;
     long len;
{
{
  int result;
  int result;
 
 
  result = fdbad (p, fd);
  result = fdbad (p, fd);
  if (p->ispipe[fd])
  if (p->ispipe[fd])
    {
    {
      p->last_errno = EINVAL;
      p->last_errno = EINVAL;
      return -1;
      return -1;
    }
    }
  if (result)
  if (result)
    return result;
    return result;
#ifdef HAVE_FTRUNCATE
#ifdef HAVE_FTRUNCATE
  result = wrap (p, ftruncate (fdmap (p, fd), len));
  result = wrap (p, ftruncate (fdmap (p, fd), len));
#else
#else
  p->last_errno = EINVAL;
  p->last_errno = EINVAL;
  result = -1;
  result = -1;
#endif
#endif
  return result;
  return result;
}
}
 
 
static int
static int
os_truncate (p, file, len)
os_truncate (p, file, len)
     host_callback *p;
     host_callback *p;
     const char *file;
     const char *file;
     long len;
     long len;
{
{
#ifdef HAVE_TRUNCATE
#ifdef HAVE_TRUNCATE
  return wrap (p, truncate (file, len));
  return wrap (p, truncate (file, len));
#else
#else
  p->last_errno = EINVAL;
  p->last_errno = EINVAL;
  return -1;
  return -1;
#endif
#endif
}
}
 
 
static int
static int
os_pipe (p, filedes)
os_pipe (p, filedes)
     host_callback *p;
     host_callback *p;
     int *filedes;
     int *filedes;
{
{
  int i;
  int i;
 
 
  /* We deliberately don't use fd 0.  It's probably stdin anyway.  */
  /* We deliberately don't use fd 0.  It's probably stdin anyway.  */
  for (i = 1; i < MAX_CALLBACK_FDS; i++)
  for (i = 1; i < MAX_CALLBACK_FDS; i++)
    {
    {
      int j;
      int j;
 
 
      if (p->fd_buddy[i] < 0)
      if (p->fd_buddy[i] < 0)
        for (j = i + 1; j < MAX_CALLBACK_FDS; j++)
        for (j = i + 1; j < MAX_CALLBACK_FDS; j++)
          if (p->fd_buddy[j] < 0)
          if (p->fd_buddy[j] < 0)
            {
            {
              /* Found two free fd:s.  Set stat to allocated and mark
              /* Found two free fd:s.  Set stat to allocated and mark
                 pipeness.  */
                 pipeness.  */
              p->fd_buddy[i] = i;
              p->fd_buddy[i] = i;
              p->fd_buddy[j] = j;
              p->fd_buddy[j] = j;
              p->ispipe[i] = j;
              p->ispipe[i] = j;
              p->ispipe[j] = -i;
              p->ispipe[j] = -i;
              filedes[0] = i;
              filedes[0] = i;
              filedes[1] = j;
              filedes[1] = j;
 
 
              /* Poison the FD map to make bugs apparent.  */
              /* Poison the FD map to make bugs apparent.  */
              p->fdmap[i] = -1;
              p->fdmap[i] = -1;
              p->fdmap[j] = -1;
              p->fdmap[j] = -1;
              return 0;
              return 0;
            }
            }
    }
    }
 
 
  p->last_errno = EMFILE;
  p->last_errno = EMFILE;
  return -1;
  return -1;
}
}
 
 
/* Stub functions for pipe support.  They should always be overridden in
/* Stub functions for pipe support.  They should always be overridden in
   targets using the pipe support, but that's up to the target.  */
   targets using the pipe support, but that's up to the target.  */
 
 
/* Called when the simulator says that the pipe at (reader, writer) is
/* Called when the simulator says that the pipe at (reader, writer) is
   now empty (so the writer should leave its waiting state).  */
   now empty (so the writer should leave its waiting state).  */
 
 
static void
static void
os_pipe_empty (p, reader, writer)
os_pipe_empty (p, reader, writer)
     host_callback *p;
     host_callback *p;
     int reader;
     int reader;
     int writer;
     int writer;
{
{
}
}
 
 
/* Called when the simulator says the pipe at (reader, writer) is now
/* Called when the simulator says the pipe at (reader, writer) is now
   non-empty (so the writer should wait).  */
   non-empty (so the writer should wait).  */
 
 
static void
static void
os_pipe_nonempty (p, reader, writer)
os_pipe_nonempty (p, reader, writer)
     host_callback *p;
     host_callback *p;
     int reader;
     int reader;
     int writer;
     int writer;
{
{
}
}
 
 
static int
static int
os_shutdown (p)
os_shutdown (p)
     host_callback *p;
     host_callback *p;
{
{
  int i, next, j;
  int i, next, j;
  for (i = 0; i < MAX_CALLBACK_FDS; i++)
  for (i = 0; i < MAX_CALLBACK_FDS; i++)
    {
    {
      int do_close = 1;
      int do_close = 1;
 
 
      /* Zero out all pipe state.  Don't call callbacks for non-empty
      /* Zero out all pipe state.  Don't call callbacks for non-empty
         pipes; the target program has likely terminated at this point
         pipes; the target program has likely terminated at this point
         or we're called at initialization time.  */
         or we're called at initialization time.  */
      p->ispipe[i] = 0;
      p->ispipe[i] = 0;
      p->pipe_buffer[i].size = 0;
      p->pipe_buffer[i].size = 0;
      p->pipe_buffer[i].buffer = NULL;
      p->pipe_buffer[i].buffer = NULL;
 
 
      next = p->fd_buddy[i];
      next = p->fd_buddy[i];
      if (next < 0)
      if (next < 0)
        continue;
        continue;
      do
      do
        {
        {
          j = next;
          j = next;
          if (j == MAX_CALLBACK_FDS)
          if (j == MAX_CALLBACK_FDS)
            do_close = 0;
            do_close = 0;
          next = p->fd_buddy[j];
          next = p->fd_buddy[j];
          p->fd_buddy[j] = -1;
          p->fd_buddy[j] = -1;
          /* At the initial call of os_init, we got -1, 0, 0, 0, ...  */
          /* At the initial call of os_init, we got -1, 0, 0, 0, ...  */
          if (next < 0)
          if (next < 0)
            {
            {
              p->fd_buddy[i] = -1;
              p->fd_buddy[i] = -1;
              do_close = 0;
              do_close = 0;
              break;
              break;
            }
            }
        }
        }
      while (j != i);
      while (j != i);
      if (do_close)
      if (do_close)
        close (p->fdmap[i]);
        close (p->fdmap[i]);
    }
    }
  return 1;
  return 1;
}
}
 
 
static int
static int
os_init (p)
os_init (p)
     host_callback *p;
     host_callback *p;
{
{
  int i;
  int i;
 
 
  os_shutdown (p);
  os_shutdown (p);
  for (i = 0; i < 3; i++)
  for (i = 0; i < 3; i++)
    {
    {
      p->fdmap[i] = i;
      p->fdmap[i] = i;
      p->fd_buddy[i] = i - 1;
      p->fd_buddy[i] = i - 1;
    }
    }
  p->fd_buddy[0] = MAX_CALLBACK_FDS;
  p->fd_buddy[0] = MAX_CALLBACK_FDS;
  p->fd_buddy[MAX_CALLBACK_FDS] = 2;
  p->fd_buddy[MAX_CALLBACK_FDS] = 2;
 
 
  p->syscall_map = cb_init_syscall_map;
  p->syscall_map = cb_init_syscall_map;
  p->errno_map = cb_init_errno_map;
  p->errno_map = cb_init_errno_map;
  p->open_map = cb_init_open_map;
  p->open_map = cb_init_open_map;
 
 
  return 1;
  return 1;
}
}
 
 
/* DEPRECATED */
/* DEPRECATED */
 
 
/* VARARGS */
/* VARARGS */
static void
static void
os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
{
{
  va_list args;
  va_list args;
  va_start (args, format);
  va_start (args, format);
 
 
  vfprintf (stdout, format, args);
  vfprintf (stdout, format, args);
  va_end (args);
  va_end (args);
}
}
 
 
/* VARARGS */
/* VARARGS */
static void
static void
os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
{
{
  vprintf (format, args);
  vprintf (format, args);
}
}
 
 
/* VARARGS */
/* VARARGS */
static void
static void
os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
{
{
  vfprintf (stderr, format, args);
  vfprintf (stderr, format, args);
}
}
 
 
/* VARARGS */
/* VARARGS */
static void
static void
os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
{
{
  va_list args;
  va_list args;
  va_start (args, format);
  va_start (args, format);
 
 
  vfprintf (stderr, format, args);
  vfprintf (stderr, format, args);
  fprintf (stderr, "\n");
  fprintf (stderr, "\n");
 
 
  va_end (args);
  va_end (args);
  exit (1);
  exit (1);
}
}
 
 
host_callback default_callback =
host_callback default_callback =
{
{
  os_close,
  os_close,
  os_get_errno,
  os_get_errno,
  os_isatty,
  os_isatty,
  os_lseek,
  os_lseek,
  os_open,
  os_open,
  os_read,
  os_read,
  os_read_stdin,
  os_read_stdin,
  os_rename,
  os_rename,
  os_system,
  os_system,
  os_time,
  os_time,
  os_unlink,
  os_unlink,
  os_write,
  os_write,
  os_write_stdout,
  os_write_stdout,
  os_flush_stdout,
  os_flush_stdout,
  os_write_stderr,
  os_write_stderr,
  os_flush_stderr,
  os_flush_stderr,
 
 
  os_stat,
  os_stat,
  os_fstat,
  os_fstat,
  os_lstat,
  os_lstat,
 
 
  os_ftruncate,
  os_ftruncate,
  os_truncate,
  os_truncate,
 
 
  os_pipe,
  os_pipe,
  os_pipe_empty,
  os_pipe_empty,
  os_pipe_nonempty,
  os_pipe_nonempty,
 
 
  os_poll_quit,
  os_poll_quit,
 
 
  os_shutdown,
  os_shutdown,
  os_init,
  os_init,
 
 
  os_printf_filtered,  /* deprecated */
  os_printf_filtered,  /* deprecated */
 
 
  os_vprintf_filtered,
  os_vprintf_filtered,
  os_evprintf_filtered,
  os_evprintf_filtered,
  os_error,
  os_error,
 
 
  0,             /* last errno */
  0,             /* last errno */
 
 
  { 0, },        /* fdmap */
  { 0, },        /* fdmap */
  { -1, },      /* fd_buddy */
  { -1, },      /* fd_buddy */
  { 0, },        /* ispipe */
  { 0, },        /* ispipe */
  { { 0, 0 }, }, /* pipe_buffer */
  { { 0, 0 }, }, /* pipe_buffer */
 
 
  0, /* syscall_map */
  0, /* syscall_map */
  0, /* errno_map */
  0, /* errno_map */
  0, /* open_map */
  0, /* open_map */
  0, /* signal_map */
  0, /* signal_map */
  0, /* stat_map */
  0, /* stat_map */
 
 
  /* Defaults expected to be overridden at initialization, where needed.  */
  /* Defaults expected to be overridden at initialization, where needed.  */
  BFD_ENDIAN_UNKNOWN, /* target_endian */
  BFD_ENDIAN_UNKNOWN, /* target_endian */
  4, /* target_sizeof_int */
  4, /* target_sizeof_int */
 
 
  HOST_CALLBACK_MAGIC,
  HOST_CALLBACK_MAGIC,
};
};


/* Read in a file describing the target's system call values.
/* Read in a file describing the target's system call values.
   E.g. maybe someone will want to use something other than newlib.
   E.g. maybe someone will want to use something other than newlib.
   This assumes that the basic system call recognition and value passing/
   This assumes that the basic system call recognition and value passing/
   returning is supported.  So maybe some coding/recompilation will be
   returning is supported.  So maybe some coding/recompilation will be
   necessary, but not as much.
   necessary, but not as much.
 
 
   If an error occurs, the existing mapping is not changed.  */
   If an error occurs, the existing mapping is not changed.  */
 
 
CB_RC
CB_RC
cb_read_target_syscall_maps (cb, file)
cb_read_target_syscall_maps (cb, file)
     host_callback *cb;
     host_callback *cb;
     const char *file;
     const char *file;
{
{
  CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
  CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
  const char *stat_map;
  const char *stat_map;
  FILE *f;
  FILE *f;
 
 
  if ((f = fopen (file, "r")) == NULL)
  if ((f = fopen (file, "r")) == NULL)
    return CB_RC_ACCESS;
    return CB_RC_ACCESS;
 
 
  /* ... read in and parse file ... */
  /* ... read in and parse file ... */
 
 
  fclose (f);
  fclose (f);
  return CB_RC_NO_MEM; /* FIXME:wip */
  return CB_RC_NO_MEM; /* FIXME:wip */
 
 
  /* Free storage allocated for any existing maps.  */
  /* Free storage allocated for any existing maps.  */
  if (cb->syscall_map)
  if (cb->syscall_map)
    free (cb->syscall_map);
    free (cb->syscall_map);
  if (cb->errno_map)
  if (cb->errno_map)
    free (cb->errno_map);
    free (cb->errno_map);
  if (cb->open_map)
  if (cb->open_map)
    free (cb->open_map);
    free (cb->open_map);
  if (cb->signal_map)
  if (cb->signal_map)
    free (cb->signal_map);
    free (cb->signal_map);
  if (cb->stat_map)
  if (cb->stat_map)
    free ((PTR) cb->stat_map);
    free ((PTR) cb->stat_map);
 
 
  cb->syscall_map = syscall_map;
  cb->syscall_map = syscall_map;
  cb->errno_map = errno_map;
  cb->errno_map = errno_map;
  cb->open_map = open_map;
  cb->open_map = open_map;
  cb->signal_map = signal_map;
  cb->signal_map = signal_map;
  cb->stat_map = stat_map;
  cb->stat_map = stat_map;
 
 
  return CB_RC_OK;
  return CB_RC_OK;
}
}
 
 
/* Translate the target's version of a syscall number to the host's.
/* Translate the target's version of a syscall number to the host's.
   This isn't actually the host's version, rather a canonical form.
   This isn't actually the host's version, rather a canonical form.
   ??? Perhaps this should be renamed to ..._canon_syscall.  */
   ??? Perhaps this should be renamed to ..._canon_syscall.  */
 
 
int
int
cb_target_to_host_syscall (cb, target_val)
cb_target_to_host_syscall (cb, target_val)
     host_callback *cb;
     host_callback *cb;
     int target_val;
     int target_val;
{
{
  CB_TARGET_DEFS_MAP *m;
  CB_TARGET_DEFS_MAP *m;
 
 
  for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
  for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
    if (m->target_val == target_val)
    if (m->target_val == target_val)
      return m->host_val;
      return m->host_val;
 
 
  return -1;
  return -1;
}
}
 
 
/* FIXME: sort tables if large.
/* FIXME: sort tables if large.
   Alternatively, an obvious improvement for errno conversion is
   Alternatively, an obvious improvement for errno conversion is
   to machine generate a function with a large switch().  */
   to machine generate a function with a large switch().  */
 
 
/* Translate the host's version of errno to the target's.  */
/* Translate the host's version of errno to the target's.  */
 
 
int
int
cb_host_to_target_errno (cb, host_val)
cb_host_to_target_errno (cb, host_val)
     host_callback *cb;
     host_callback *cb;
     int host_val;
     int host_val;
{
{
  CB_TARGET_DEFS_MAP *m;
  CB_TARGET_DEFS_MAP *m;
 
 
  for (m = &cb->errno_map[0]; m->host_val; ++m)
  for (m = &cb->errno_map[0]; m->host_val; ++m)
    if (m->host_val == host_val)
    if (m->host_val == host_val)
      return m->target_val;
      return m->target_val;
 
 
  /* ??? Which error to return in this case is up for grabs.
  /* ??? Which error to return in this case is up for grabs.
     Note that some missing values may have standard alternatives.
     Note that some missing values may have standard alternatives.
     For now return 0 and require caller to deal with it.  */
     For now return 0 and require caller to deal with it.  */
  return 0;
  return 0;
}
}
 
 
/* Given a set of target bitmasks for the open system call,
/* Given a set of target bitmasks for the open system call,
   return the host equivalent.
   return the host equivalent.
   Mapping open flag values is best done by looping so there's no need
   Mapping open flag values is best done by looping so there's no need
   to machine generate this function.  */
   to machine generate this function.  */
 
 
int
int
cb_target_to_host_open (cb, target_val)
cb_target_to_host_open (cb, target_val)
     host_callback *cb;
     host_callback *cb;
     int target_val;
     int target_val;
{
{
  int host_val = 0;
  int host_val = 0;
  CB_TARGET_DEFS_MAP *m;
  CB_TARGET_DEFS_MAP *m;
 
 
  for (m = &cb->open_map[0]; m->host_val != -1; ++m)
  for (m = &cb->open_map[0]; m->host_val != -1; ++m)
    {
    {
      switch (m->target_val)
      switch (m->target_val)
        {
        {
          /* O_RDONLY can be (and usually is) 0 which needs to be treated
          /* O_RDONLY can be (and usually is) 0 which needs to be treated
             specially.  */
             specially.  */
        case TARGET_O_RDONLY :
        case TARGET_O_RDONLY :
        case TARGET_O_WRONLY :
        case TARGET_O_WRONLY :
        case TARGET_O_RDWR :
        case TARGET_O_RDWR :
          if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
          if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
              == m->target_val)
              == m->target_val)
            host_val |= m->host_val;
            host_val |= m->host_val;
          /* Handle the host/target differentiating between binary and
          /* Handle the host/target differentiating between binary and
             text mode.  Only one case is of importance */
             text mode.  Only one case is of importance */
#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
          host_val |= O_BINARY;
          host_val |= O_BINARY;
#endif
#endif
          break;
          break;
        default :
        default :
          if ((m->target_val & target_val) == m->target_val)
          if ((m->target_val & target_val) == m->target_val)
            host_val |= m->host_val;
            host_val |= m->host_val;
          break;
          break;
        }
        }
    }
    }
 
 
  return host_val;
  return host_val;
}
}
 
 
/* Utility for e.g. cb_host_to_target_stat to store values in the target's
/* Utility for e.g. cb_host_to_target_stat to store values in the target's
   stat struct.  */
   stat struct.  */
 
 
void
void
cb_store_target_endian (cb, p, size, val)
cb_store_target_endian (cb, p, size, val)
     host_callback *cb;
     host_callback *cb;
     char *p;
     char *p;
     int size;
     int size;
     long val; /* ??? must be as big as target word size */
     long val; /* ??? must be as big as target word size */
{
{
  if (cb->target_endian == BFD_ENDIAN_BIG)
  if (cb->target_endian == BFD_ENDIAN_BIG)
    {
    {
      p += size;
      p += size;
      while (size-- > 0)
      while (size-- > 0)
        {
        {
          *--p = val;
          *--p = val;
          val >>= 8;
          val >>= 8;
        }
        }
    }
    }
  else
  else
    {
    {
      while (size-- > 0)
      while (size-- > 0)
        {
        {
          *p++ = val;
          *p++ = val;
          val >>= 8;
          val >>= 8;
        }
        }
    }
    }
}
}
 
 
/* Translate a host's stat struct into a target's.
/* Translate a host's stat struct into a target's.
   If HS is NULL, just compute the length of the buffer required,
   If HS is NULL, just compute the length of the buffer required,
   TS is ignored.
   TS is ignored.
 
 
   The result is the size of the target's stat struct,
   The result is the size of the target's stat struct,
   or zero if an error occurred during the translation.  */
   or zero if an error occurred during the translation.  */
 
 
int
int
cb_host_to_target_stat (cb, hs, ts)
cb_host_to_target_stat (cb, hs, ts)
     host_callback *cb;
     host_callback *cb;
     const struct stat *hs;
     const struct stat *hs;
     PTR ts;
     PTR ts;
{
{
  const char *m = cb->stat_map;
  const char *m = cb->stat_map;
  char *p;
  char *p;
 
 
  if (hs == NULL)
  if (hs == NULL)
    ts = NULL;
    ts = NULL;
  p = ts;
  p = ts;
 
 
  while (m)
  while (m)
    {
    {
      char *q = strchr (m, ',');
      char *q = strchr (m, ',');
      int size;
      int size;
 
 
      /* FIXME: Use sscanf? */
      /* FIXME: Use sscanf? */
      if (q == NULL)
      if (q == NULL)
        {
        {
          /* FIXME: print error message */
          /* FIXME: print error message */
          return 0;
          return 0;
        }
        }
      size = atoi (q + 1);
      size = atoi (q + 1);
      if (size == 0)
      if (size == 0)
        {
        {
          /* FIXME: print error message */
          /* FIXME: print error message */
          return 0;
          return 0;
        }
        }
 
 
      if (hs != NULL)
      if (hs != NULL)
        {
        {
          if (0)
          if (0)
            ;
            ;
          /* Defined here to avoid emacs indigestion on a lone "else".  */
          /* Defined here to avoid emacs indigestion on a lone "else".  */
#undef ST_x
#undef ST_x
#define ST_x(FLD)                                       \
#define ST_x(FLD)                                       \
          else if (strncmp (m, #FLD, q - m) == 0)       \
          else if (strncmp (m, #FLD, q - m) == 0)       \
            cb_store_target_endian (cb, p, size, hs->FLD)
            cb_store_target_endian (cb, p, size, hs->FLD)
 
 
#ifdef HAVE_STRUCT_STAT_ST_DEV
#ifdef HAVE_STRUCT_STAT_ST_DEV
          ST_x (st_dev);
          ST_x (st_dev);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_INO
#ifdef HAVE_STRUCT_STAT_ST_INO
          ST_x (st_ino);
          ST_x (st_ino);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_MODE
#ifdef HAVE_STRUCT_STAT_ST_MODE
          ST_x (st_mode);
          ST_x (st_mode);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_NLINK
#ifdef HAVE_STRUCT_STAT_ST_NLINK
          ST_x (st_nlink);
          ST_x (st_nlink);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_UID
#ifdef HAVE_STRUCT_STAT_ST_UID
          ST_x (st_uid);
          ST_x (st_uid);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_GID
#ifdef HAVE_STRUCT_STAT_ST_GID
          ST_x (st_gid);
          ST_x (st_gid);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_RDEV
#ifdef HAVE_STRUCT_STAT_ST_RDEV
          ST_x (st_rdev);
          ST_x (st_rdev);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_SIZE
#ifdef HAVE_STRUCT_STAT_ST_SIZE
          ST_x (st_size);
          ST_x (st_size);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
          ST_x (st_blksize);
          ST_x (st_blksize);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
          ST_x (st_blocks);
          ST_x (st_blocks);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_ATIME
#ifdef HAVE_STRUCT_STAT_ST_ATIME
          ST_x (st_atime);
          ST_x (st_atime);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_MTIME
#ifdef HAVE_STRUCT_STAT_ST_MTIME
          ST_x (st_mtime);
          ST_x (st_mtime);
#endif
#endif
#ifdef HAVE_STRUCT_STAT_ST_CTIME
#ifdef HAVE_STRUCT_STAT_ST_CTIME
          ST_x (st_ctime);
          ST_x (st_ctime);
#endif
#endif
#undef ST_x
#undef ST_x
          /* FIXME:wip */
          /* FIXME:wip */
          else
          else
            /* Unsupported field, store 0.  */
            /* Unsupported field, store 0.  */
            cb_store_target_endian (cb, p, size, 0);
            cb_store_target_endian (cb, p, size, 0);
        }
        }
 
 
      p += size;
      p += size;
      m = strchr (q, ':');
      m = strchr (q, ':');
      if (m)
      if (m)
        ++m;
        ++m;
    }
    }
 
 
  return p - (char *) ts;
  return p - (char *) ts;
}
}


/* Cover functions to the vfprintf callbacks.
/* Cover functions to the vfprintf callbacks.
 
 
   ??? If one thinks of the callbacks as a subsystem onto itself [or part of
   ??? If one thinks of the callbacks as a subsystem onto itself [or part of
   a larger "remote target subsystem"] with a well defined interface, then
   a larger "remote target subsystem"] with a well defined interface, then
   one would think that the subsystem would provide these.  However, until
   one would think that the subsystem would provide these.  However, until
   one is allowed to create such a subsystem (with its own source tree
   one is allowed to create such a subsystem (with its own source tree
   independent of any particular user), such a critter can't exist.  Thus
   independent of any particular user), such a critter can't exist.  Thus
   these functions are here for the time being.  */
   these functions are here for the time being.  */
 
 
void
void
sim_cb_printf (host_callback *p, const char *fmt, ...)
sim_cb_printf (host_callback *p, const char *fmt, ...)
{
{
  va_list ap;
  va_list ap;
 
 
  va_start (ap, fmt);
  va_start (ap, fmt);
  p->vprintf_filtered (p, fmt, ap);
  p->vprintf_filtered (p, fmt, ap);
  va_end (ap);
  va_end (ap);
}
}
 
 
void
void
sim_cb_eprintf (host_callback *p, const char *fmt, ...)
sim_cb_eprintf (host_callback *p, const char *fmt, ...)
{
{
  va_list ap;
  va_list ap;
 
 
  va_start (ap, fmt);
  va_start (ap, fmt);
  p->evprintf_filtered (p, fmt, ap);
  p->evprintf_filtered (p, fmt, ap);
  va_end (ap);
  va_end (ap);
}
}
 
 
int
int
cb_is_stdin (host_callback *cb, int fd)
cb_is_stdin (host_callback *cb, int fd)
{
{
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0;
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 0;
}
}
 
 
int
int
cb_is_stdout (host_callback *cb, int fd)
cb_is_stdout (host_callback *cb, int fd)
{
{
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1;
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 1;
}
}
 
 
int
int
cb_is_stderr (host_callback *cb, int fd)
cb_is_stderr (host_callback *cb, int fd)
{
{
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2;
  return fdbad (cb, fd) ? 0 : fdmap (cb, fd) == 2;
}
}
 
 

powered by: WebSVN 2.1.0

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