Fix compile time warning messages.
[deliverable/binutils-gdb.git] / sim / common / callback.c
index 764d4b67f1b6768ac18109ca4418451ec4cff38d..19acca0e99889a7a3281a8521375b03f68f823fe 100644 (file)
@@ -1,6 +1,6 @@
-/* Host callback routines for GDB.
-   Copyright 1995, 1996 Free Software Foundation, Inc.
-   Contributed by Cygnus Support.
+/* Remote target callback routines.
+   Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+   Contributed by Cygnus Solutions.
 
    This file is part of GDB.
 
    GNU General Public License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   along with GAS; see the file COPYING.  If not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* This file provides a standard way for targets to talk to the host OS
    level.  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 #include "ansidecl.h"
 #ifdef ANSI_PROTOTYPES
 #include <stdarg.h>
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#ifdef HAVE_STRINGS_H
+#include <strings.h>
+#endif
+#endif
 #include <errno.h>
 #include <fcntl.h>
 #include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include "callback.h"
 #include "targ-vals.h"
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/* ??? 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
+   sim-utils.h.  */
+void sim_cb_printf 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_errno_map[];
+extern CB_TARGET_DEFS_MAP cb_init_open_map[];
+
+extern int system PARAMS ((const char *));
+
 static int os_init PARAMS ((host_callback *));
 static int os_shutdown PARAMS ((host_callback *));
 static int os_unlink PARAMS ((host_callback *, const char *));
@@ -44,6 +72,9 @@ static long os_time PARAMS ((host_callback *, long *));
 static int os_system PARAMS ((host_callback *, 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 void os_flush_stdout PARAMS ((host_callback *));
+static int os_write_stderr PARAMS ((host_callback *, const char *, int));
+static void os_flush_stderr PARAMS ((host_callback *));
 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 PARAMS ((host_callback *, int, char *, int));
@@ -52,6 +83,9 @@ static int os_lseek PARAMS ((host_callback *, int, long, int));
 static int os_isatty PARAMS ((host_callback *, int));
 static int os_get_errno PARAMS ((host_callback *));
 static int os_close PARAMS ((host_callback *, int));
+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_error PARAMS ((host_callback *, const char *, ...));
 static int fdmap PARAMS ((host_callback *, int));
 static int fdbad PARAMS ((host_callback *, int));
 static int wrap PARAMS ((host_callback *, int));
@@ -102,14 +136,60 @@ os_close (p, fd)
   if (result)
     return result;
   result = wrap (p, close (fdmap (p, fd)));
+  if (result == 0 && !p->alwaysopen[fd])
+    p->fdopen[fd] = 0;
+
   return result;
 }
 
+
+/* taken from gdb/util.c:notice_quit() - should be in a library */
+
+
+#if defined(__GO32__) || defined (_MSC_VER)
+static int
+os_poll_quit (p)
+     host_callback *p;
+{
+#if defined(__GO32__)
+  int kbhit ();
+  int getkey ();
+  if (kbhit ())
+    {
+      int k = getkey ();
+      if (k == 1)
+       {
+         return 1;
+       }
+      else if (k == 2)
+       {
+         return 1;
+       }
+      else 
+       {
+         sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
+       }
+    }
+#endif
+#if defined (_MSC_VER)
+  /* NB - this will not compile! */
+  int k = win32pollquit();
+  if (k == 1)
+    return 1;
+  else if (k == 2)
+    return 1;
+#endif
+  return 0;
+}
+#else
+#define os_poll_quit 0
+#endif /* defined(__GO32__) || defined(_MSC_VER) */
+
 static int 
 os_get_errno (p)
      host_callback *p;
 {
-  return host_to_target_errno (p->last_errno);
+  return cb_host_to_target_errno (p, p->last_errno);
 }
 
 
@@ -124,6 +204,7 @@ os_isatty (p, fd)
   if (result)
     return result;
   result = wrap (p, isatty (fdmap (p, fd)));
+
   return result;
 }
 
@@ -154,7 +235,7 @@ os_open (p, name, flags)
     {
       if (!p->fdopen[i])
        {
-         int f = open (name, target_to_host_open (flags));
+         int f = open (name, cb_target_to_host_open (p, flags), 0644);
          if (f < 0)
            {
              p->last_errno = errno;
@@ -202,21 +283,57 @@ os_write (p, fd, buf, len)
      int len;
 {
   int result;
+  int real_fd;
 
   result = fdbad (p, fd);
   if (result)
     return result;
-  result = wrap (p, write (fdmap (p, fd), buf, len));
+  real_fd = fdmap (p, fd);
+  switch (real_fd)
+    {
+    default:
+      result = wrap (p, write (real_fd, buf, len));
+      break;
+    case 1:
+      result = p->write_stdout (p, buf, len);
+      break;
+    case 2:
+      result = p->write_stderr (p, buf, len);
+      break;
+    }
   return result;
 }
 
 static int 
 os_write_stdout (p, buf, len)
-     host_callback *p;
+     host_callback *p ATTRIBUTE_UNUSED;
      const char *buf;
      int len;
 {
-  return os_write (p, 1, buf, len);
+  return fwrite (buf, 1, len, stdout);
+}
+
+static void
+os_flush_stdout (p)
+     host_callback *p ATTRIBUTE_UNUSED;
+{
+  fflush (stdout);
+}
+
+static int 
+os_write_stderr (p, buf, len)
+     host_callback *p ATTRIBUTE_UNUSED;
+     const char *buf;
+     int len;
+{
+  return fwrite (buf, 1, len, stderr);
+}
+
+static void
+os_flush_stderr (p)
+     host_callback *p ATTRIBUTE_UNUSED;
+{
+  fflush (stderr);
 }
 
 static int 
@@ -254,6 +371,33 @@ os_unlink (p, f1)
   return wrap (p, unlink (f1));
 }
 
+static int
+os_stat (p, file, buf)
+     host_callback *p;
+     const char *file;
+     struct stat *buf;
+{
+  /* ??? There is an issue of when to translate to the target layout.
+     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
+     I'm not sure the flexibility will ever be useful.  */
+  return wrap (p, stat (file, buf));
+}
+
+static int
+os_fstat (p, fd, buf)
+     host_callback *p;
+     int fd;
+     struct stat *buf;
+{
+  if (fdbad (p, fd))
+    return -1;
+  /* ??? There is an issue of when to translate to the target layout.
+     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
+     I'm not sure the flexibility will ever be useful.  */
+  return wrap (p, fstat (fdmap (p, fd), buf));
+}
 
 static int
 os_shutdown (p)
@@ -271,24 +415,32 @@ os_shutdown (p)
 }
 
 static int
-os_init(p)
+os_init (p)
      host_callback *p;
 {
   int i;
+
   os_shutdown (p);
-  for (i= 0; i < 3; i++)
+  for (i = 0; i < 3; i++)
     {
       p->fdmap[i] = i;
       p->fdopen[i] = 1;
       p->alwaysopen[i] = 1;
     }
+
+  p->syscall_map = cb_init_syscall_map;
+  p->errno_map = cb_init_errno_map;
+  p->open_map = cb_init_open_map;
+
   return 1;
 }
 
+/* DEPRECIATED */
+
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_printf_filtered (host_callback *p, const char *format, ...)
+os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
 #else
 os_printf_filtered (p, va_alist)
      host_callback *p;
@@ -305,15 +457,42 @@ os_printf_filtered (p, va_alist)
   format = va_arg (args, char *);
 #endif
 
+  vfprintf (stdout, format, args);
+  va_end (args);
+}
+
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
+#else
+os_vprintf_filtered (p, format, args)
+     host_callback *p;
+     const char *format;
+     va_list args;
+#endif
+{
   vprintf (format, args);
+}
 
-  va_end (args);
+/* VARARGS */
+static void
+#ifdef ANSI_PROTOTYPES
+os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
+#else
+os_evprintf_filtered (p, format, args)
+     host_callback *p;
+     const char *format;
+     va_list args;
+#endif
+{
+  vfprintf (stderr, format, args);
 }
 
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_error (host_callback *p, const char *format, ...)
+os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
 #else
 os_error (p, va_alist)
      host_callback *p;
@@ -334,7 +513,7 @@ os_error (p, va_alist)
   fprintf (stderr, "\n");
 
   va_end (args);
-  exit (EXIT_FAILURE);
+  exit (1);
 }
 
 host_callback default_callback =
@@ -352,31 +531,117 @@ host_callback default_callback =
   os_unlink,
   os_write,
   os_write_stdout,
+  os_flush_stdout,
+  os_write_stderr,
+  os_flush_stderr,
+
+  os_stat,
+  os_fstat,
+
+  os_poll_quit,
 
   os_shutdown,
   os_init,
 
-  os_printf_filtered,
+  os_printf_filtered,  /* deprecated */
+
+  os_vprintf_filtered,
+  os_evprintf_filtered,
   os_error,
 
   0,           /* last errno */
+
+  { 0, },      /* fdmap */
+  { 0, },      /* fdopen */
+  { 0, },      /* alwaysopen */
+
+  0, /* syscall_map */
+  0, /* errno_map */
+  0, /* open_map */
+  0, /* signal_map */
+  0, /* stat_map */
+       
+  HOST_CALLBACK_MAGIC,
 };
 \f
-/* FIXME: Need to add hooks so target can tweak as necessary.  */
+/* Read in a file describing the target's system call values.
+   E.g. maybe someone will want to use something other than newlib.
+   This assumes that the basic system call recognition and value passing/
+   returning is supported.  So maybe some coding/recompilation will be
+   necessary, but not as much.
+
+   If an error occurs, the existing mapping is not changed.  */
+
+CB_RC
+cb_read_target_syscall_maps (cb, file)
+     host_callback *cb;
+     const char *file;
+{
+  CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
+  const char *stat_map;
+  FILE *f;
+
+  if ((f = fopen (file, "r")) == NULL)
+    return CB_RC_ACCESS;
+
+  /* ... read in and parse file ... */
+
+  fclose (f);
+  return CB_RC_NO_MEM; /* FIXME:wip */
+
+  /* Free storage allocated for any existing maps.  */
+  if (cb->syscall_map)
+    free (cb->syscall_map);
+  if (cb->errno_map)
+    free (cb->errno_map);
+  if (cb->open_map)
+    free (cb->open_map);
+  if (cb->signal_map)
+    free (cb->signal_map);
+  if (cb->stat_map)
+    free ((PTR) cb->stat_map);
+
+  cb->syscall_map = syscall_map;
+  cb->errno_map = errno_map;
+  cb->open_map = open_map;
+  cb->signal_map = signal_map;
+  cb->stat_map = stat_map;
+
+  return CB_RC_OK;
+}
 
-/* FIXME: struct stat conversion is missing.  */
+/* 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.
+   ??? Perhaps this should be renamed to ..._canon_syscall.  */
+
+int
+cb_target_to_host_syscall (cb, target_val)
+     host_callback *cb;
+     int target_val;
+{
+  CB_TARGET_DEFS_MAP *m;
+
+  for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
+    if (m->target_val == target_val)
+      return m->host_val;
+
+  return -1;
+}
 
 /* FIXME: sort tables if large.
    Alternatively, an obvious improvement for errno conversion is
    to machine generate a function with a large switch().  */
 
+/* Translate the host's version of errno to the target's.  */
+
 int
-host_to_target_errno (host_val)
+cb_host_to_target_errno (cb, host_val)
+     host_callback *cb;
      int host_val;
 {
-  target_defs_map *m;
+  CB_TARGET_DEFS_MAP *m;
 
-  for (m = &errno_map[0]; m->host_val; ++m)
+  for (m = &cb->errno_map[0]; m->host_val; ++m)
     if (m->host_val == host_val)
       return m->target_val;
 
@@ -392,13 +657,14 @@ host_to_target_errno (host_val)
    to machine generate this function.  */
 
 int
-target_to_host_open (target_val)
+cb_target_to_host_open (cb, target_val)
+     host_callback *cb;
      int target_val;
 {
   int host_val = 0;
-  target_defs_map *m;
+  CB_TARGET_DEFS_MAP *m;
 
-  for (m = &open_map[0]; m->host_val != -1; ++m)
+  for (m = &cb->open_map[0]; m->host_val != -1; ++m)
     {
       switch (m->target_val)
        {
@@ -410,6 +676,11 @@ target_to_host_open (target_val)
          if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
              == m->target_val)
            host_val |= m->host_val;
+         /* Handle the host/target differentiating between binary and
+             text mode.  Only one case is of importance */
+#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
+         host_val |= O_BINARY;
+#endif
          break;
        default :
          if ((m->target_val & target_val) == m->target_val)
@@ -420,3 +691,120 @@ target_to_host_open (target_val)
 
   return host_val;
 }
+
+/* Utility for cb_host_to_target_stat to store values in the target's
+   stat struct.  */
+
+static void
+store (p, size, val, big_p)
+     char *p;
+     int size;
+     long val; /* ??? must be as big as target word size */
+     int big_p;
+{
+  if (big_p)
+    {
+      p += size;
+      while (size-- > 0)
+       {
+         *--p = val;
+         val >>= 8;
+       }
+    }
+  else
+    {
+      while (size-- > 0)
+       {
+         *p++ = val;
+         val >>= 8;
+       }
+    }
+}
+
+/* Translate a host's stat struct into a target's.
+   If HS is NULL, just compute the length of the buffer required,
+   TS is ignored.
+
+   The result is the size of the target's stat struct,
+   or zero if an error occured during the translation.  */
+
+int
+cb_host_to_target_stat (cb, hs, ts)
+     host_callback *cb;
+     const struct stat *hs;
+     PTR ts;
+{
+  const char *m = cb->stat_map;
+  char *p;
+  int big_p = 0;
+
+  if (hs == NULL)
+    ts = NULL;
+  p = ts;
+
+  while (m)
+    {
+      char *q = strchr (m, ',');
+      int size;
+
+      /* FIXME: Use sscanf? */
+      if (q == NULL)
+       {
+         /* FIXME: print error message */
+         return 0;
+       }
+      size = atoi (q + 1);
+      if (size == 0)
+       {
+         /* FIXME: print error message */
+         return 0;
+       }
+
+      if (hs != NULL)
+       {
+         if (strncmp (m, "st_dev", q - m) == 0)
+           store (p, size, hs->st_dev, big_p);
+         else if (strncmp (m, "st_ino", q - m) == 0)
+           store (p, size, hs->st_ino, big_p);
+         /* FIXME:wip */
+         else
+           store (p, size, 0, big_p); /* unsupported field, store 0 */
+       }
+
+      p += size;
+      m = strchr (q, ':');
+      if (m)
+       ++m;
+    }
+
+  return p - (char *) ts;
+}
+\f
+/* Cover functions to the vfprintf callbacks.
+
+   ??? 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
+   one would think that the subsystem would provide these.  However, until
+   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
+   these functions are here for the time being.  */
+
+void
+sim_cb_printf (host_callback *p, const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  p->vprintf_filtered (p, fmt, ap);
+  va_end (ap);
+}
+
+void
+sim_cb_eprintf (host_callback *p, const char *fmt, ...)
+{
+  va_list ap;
+
+  va_start (ap, fmt);
+  p->evprintf_filtered (p, fmt, ap);
+  va_end (ap);
+}
This page took 0.030669 seconds and 4 git commands to generate.