Tweak comment.
[deliverable/binutils-gdb.git] / sim / common / callback.c
CommitLineData
f7abc1ca 1/* Remote target callback routines.
052d7984 2 Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
f7abc1ca 3 Contributed by Cygnus Solutions.
966f47b4
DE
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
f7abc1ca
DE
18 along with GAS; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
966f47b4
DE
20
21/* This file provides a standard way for targets to talk to the host OS
22 level. */
23
c45adab0
MM
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
966f47b4
DE
27#include "ansidecl.h"
28#ifdef ANSI_PROTOTYPES
29#include <stdarg.h>
30#else
31#include <varargs.h>
32#endif
33#include <stdio.h>
34#ifdef HAVE_STDLIB_H
35#include <stdlib.h>
36#endif
f7abc1ca
DE
37#ifdef HAVE_STRING_H
38#include <string.h>
39#else
40#ifdef HAVE_STRINGS_H
41#include <strings.h>
42#endif
43#endif
966f47b4
DE
44#include <errno.h>
45#include <fcntl.h>
46#include <time.h>
f7abc1ca
DE
47#include <sys/types.h>
48#include <sys/stat.h>
966f47b4
DE
49#include "callback.h"
50#include "targ-vals.h"
51
248c1fb8 52#ifdef HAVE_UNISTD_H
c45adab0
MM
53#include <unistd.h>
54#endif
55
f90b720b
AC
56/* ??? sim_cb_printf should be cb_printf, but until the callback support is
57 broken out of the simulator directory, these are here to not require
58 sim-utils.h. */
59void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
60void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
61
f7abc1ca
DE
62extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
63extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
64extern CB_TARGET_DEFS_MAP cb_init_open_map[];
65
c45adab0
MM
66extern int system PARAMS ((const char *));
67
966f47b4
DE
68static int os_init PARAMS ((host_callback *));
69static int os_shutdown PARAMS ((host_callback *));
70static int os_unlink PARAMS ((host_callback *, const char *));
71static long os_time PARAMS ((host_callback *, long *));
72static int os_system PARAMS ((host_callback *, const char *));
73static int os_rename PARAMS ((host_callback *, const char *, const char *));
74static int os_write_stdout PARAMS ((host_callback *, const char *, int));
248c1fb8
JL
75static void os_flush_stdout PARAMS ((host_callback *));
76static int os_write_stderr PARAMS ((host_callback *, const char *, int));
77static void os_flush_stderr PARAMS ((host_callback *));
966f47b4
DE
78static int os_write PARAMS ((host_callback *, int, const char *, int));
79static int os_read_stdin PARAMS ((host_callback *, char *, int));
80static int os_read PARAMS ((host_callback *, int, char *, int));
81static int os_open PARAMS ((host_callback *, const char *, int));
82static int os_lseek PARAMS ((host_callback *, int, long, int));
83static int os_isatty PARAMS ((host_callback *, int));
84static int os_get_errno PARAMS ((host_callback *));
85static int os_close PARAMS ((host_callback *, int));
248c1fb8
JL
86static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
87static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
88static void os_error PARAMS ((host_callback *, const char *, ...));
966f47b4
DE
89static int fdmap PARAMS ((host_callback *, int));
90static int fdbad PARAMS ((host_callback *, int));
91static int wrap PARAMS ((host_callback *, int));
f7abc1ca 92static int enosys PARAMS ((host_callback *, int));
966f47b4
DE
93
94/* Set the callback copy of errno from what we see now. */
95
96static int
97wrap (p, val)
98 host_callback *p;
99 int val;
100{
101 p->last_errno = errno;
102 return val;
103}
104
f7abc1ca
DE
105/* Return a value indicating the system call isn't present. */
106
107static int
108enosys (p, result)
109 host_callback *p;
110 int result;
111{
112#ifdef ENOSYS
113 p->last_errno = ENOSYS;
114#else
115 p->last_errno = EINVAL;
116#endif
117 return result;
118}
119
966f47b4
DE
120/* Make sure the FD provided is ok. If not, return non-zero
121 and set errno. */
122
123static int
124fdbad (p, fd)
125 host_callback *p;
126 int fd;
127{
128 if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
129 {
130 p->last_errno = EINVAL;
131 return -1;
132 }
133 return 0;
134}
135
136static int
137fdmap (p, fd)
138 host_callback *p;
139 int fd;
140{
141 return p->fdmap[fd];
142}
143
144static int
145os_close (p, fd)
146 host_callback *p;
147 int fd;
148{
149 int result;
150
151 result = fdbad (p, fd);
152 if (result)
153 return result;
154 result = wrap (p, close (fdmap (p, fd)));
248c1fb8
JL
155 if(result == 0 && !p->alwaysopen[fd])
156 p->fdopen[fd] = 0;
157
966f47b4
DE
158 return result;
159}
160
248c1fb8 161
f7abc1ca 162/* taken from gdb/util.c:notice_quit() - should be in a library */
248c1fb8
JL
163
164
f7abc1ca 165#if defined(__GO32__) || defined (_MSC_VER)
052d7984 166static int
248c1fb8
JL
167os_poll_quit (p)
168 host_callback *p;
169{
f7abc1ca 170#if defined(__GO32__)
f90b720b
AC
171 int kbhit ();
172 int getkey ();
248c1fb8
JL
173 if (kbhit ())
174 {
175 int k = getkey ();
176 if (k == 1)
177 {
178 return 1;
179 }
180 else if (k == 2)
181 {
182 return 1;
183 }
184 else
185 {
052d7984 186 sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
248c1fb8
JL
187 }
188 }
f7abc1ca
DE
189#endif
190#if defined (_MSC_VER)
248c1fb8
JL
191 /* NB - this will not compile! */
192 int k = win32pollquit();
193 if (k == 1)
194 return 1;
195 else if (k == 2)
196 return 1;
f7abc1ca 197#endif
248c1fb8
JL
198 return 0;
199}
200#else
201#define os_poll_quit 0
f7abc1ca 202#endif /* defined(__GO32__) || defined(_MSC_VER) */
248c1fb8 203
966f47b4
DE
204static int
205os_get_errno (p)
206 host_callback *p;
207{
f7abc1ca 208 return cb_host_to_target_errno (p, p->last_errno);
966f47b4
DE
209}
210
211
212static int
213os_isatty (p, fd)
214 host_callback *p;
215 int fd;
216{
217 int result;
218
219 result = fdbad (p, fd);
220 if (result)
221 return result;
222 result = wrap (p, isatty (fdmap (p, fd)));
248c1fb8 223
966f47b4
DE
224 return result;
225}
226
227static int
228os_lseek (p, fd, off, way)
229 host_callback *p;
230 int fd;
231 long off;
232 int way;
233{
234 int result;
235
236 result = fdbad (p, fd);
237 if (result)
238 return result;
239 result = lseek (fdmap (p, fd), off, way);
240 return result;
241}
242
243static int
244os_open (p, name, flags)
245 host_callback *p;
246 const char *name;
052d7984 247 int flags;
966f47b4
DE
248{
249 int i;
250 for (i = 0; i < MAX_CALLBACK_FDS; i++)
251 {
252 if (!p->fdopen[i])
253 {
f7abc1ca 254 int f = open (name, cb_target_to_host_open (p, flags), 0644);
966f47b4
DE
255 if (f < 0)
256 {
257 p->last_errno = errno;
258 return f;
259 }
260 p->fdopen[i] = 1;
261 p->fdmap[i] = f;
262 return i;
263 }
264 }
265 p->last_errno = EMFILE;
266 return -1;
267}
268
269static int
270os_read (p, fd, buf, len)
271 host_callback *p;
272 int fd;
273 char *buf;
274 int len;
275{
276 int result;
277
278 result = fdbad (p, fd);
279 if (result)
280 return result;
281 result = wrap (p, read (fdmap (p, fd), buf, len));
282 return result;
283}
284
285static int
286os_read_stdin (p, buf, len)
287 host_callback *p;
288 char *buf;
289 int len;
290{
291 return wrap (p, read (0, buf, len));
292}
293
294static int
295os_write (p, fd, buf, len)
296 host_callback *p;
297 int fd;
298 const char *buf;
299 int len;
300{
301 int result;
f7abc1ca 302 int real_fd;
966f47b4
DE
303
304 result = fdbad (p, fd);
305 if (result)
306 return result;
f7abc1ca
DE
307 real_fd = fdmap (p, fd);
308 switch (real_fd)
309 {
310 default:
311 result = wrap (p, write (real_fd, buf, len));
312 break;
313 case 1:
314 result = p->write_stdout (p, buf, len);
315 break;
316 case 2:
317 result = p->write_stderr (p, buf, len);
318 break;
319 }
966f47b4
DE
320 return result;
321}
322
323static int
324os_write_stdout (p, buf, len)
325 host_callback *p;
326 const char *buf;
327 int len;
328{
248c1fb8
JL
329 return fwrite(buf, 1, len, stdout);
330}
331
332static void
333os_flush_stdout (p)
334 host_callback *p;
335{
336 fflush (stdout);
337}
338
339static int
340os_write_stderr (p, buf, len)
341 host_callback *p;
342 const char *buf;
343 int len;
344{
345 return fwrite(buf, 1, len, stderr);
346}
347
348static void
349os_flush_stderr (p)
350 host_callback *p;
351{
352 fflush (stderr);
966f47b4
DE
353}
354
355static int
356os_rename (p, f1, f2)
357 host_callback *p;
358 const char *f1;
359 const char *f2;
360{
361 return wrap (p, rename (f1, f2));
362}
363
364
365static int
366os_system (p, s)
367 host_callback *p;
368 const char *s;
369{
370 return wrap (p, system (s));
371}
372
373static long
374os_time (p, t)
375 host_callback *p;
376 long *t;
377{
378 return wrap (p, time (t));
379}
380
381
382static int
383os_unlink (p, f1)
384 host_callback *p;
385 const char *f1;
386{
387 return wrap (p, unlink (f1));
388}
389
f7abc1ca
DE
390static int
391os_stat (p, file, buf)
392 host_callback *p;
393 const char *file;
394 PTR buf;
395{
396 return wrap (p, stat (file, buf));
397}
398
399static int
400os_fstat (p, fd, buf)
401 host_callback *p;
402 int fd;
403 PTR buf;
404{
405 return wrap (p, fstat (fd, buf));
406}
966f47b4
DE
407
408static int
409os_shutdown (p)
410 host_callback *p;
411{
412 int i;
413 for (i = 0; i < MAX_CALLBACK_FDS; i++)
414 {
415 if (p->fdopen[i] && !p->alwaysopen[i]) {
416 close (p->fdmap[i]);
417 p->fdopen[i] = 0;
418 }
419 }
420 return 1;
421}
422
423static int
f7abc1ca 424os_init (p)
966f47b4
DE
425 host_callback *p;
426{
427 int i;
f7abc1ca 428
966f47b4 429 os_shutdown (p);
f7abc1ca 430 for (i = 0; i < 3; i++)
966f47b4
DE
431 {
432 p->fdmap[i] = i;
433 p->fdopen[i] = 1;
434 p->alwaysopen[i] = 1;
435 }
f7abc1ca
DE
436
437 p->syscall_map = cb_init_syscall_map;
438 p->errno_map = cb_init_errno_map;
439 p->open_map = cb_init_open_map;
440
966f47b4
DE
441 return 1;
442}
443
248c1fb8
JL
444/* DEPRECIATED */
445
966f47b4
DE
446/* VARARGS */
447static void
448#ifdef ANSI_PROTOTYPES
449os_printf_filtered (host_callback *p, const char *format, ...)
450#else
451os_printf_filtered (p, va_alist)
452 host_callback *p;
453 va_dcl
454#endif
455{
456 va_list args;
457#ifdef ANSI_PROTOTYPES
458 va_start (args, format);
459#else
460 char *format;
461
462 va_start (args);
463 format = va_arg (args, char *);
464#endif
465
248c1fb8
JL
466 vfprintf (stdout, format, args);
467 va_end (args);
468}
469
470/* VARARGS */
471static void
472#ifdef ANSI_PROTOTYPES
473os_vprintf_filtered (host_callback *p, const char *format, va_list args)
474#else
475os_vprintf_filtered (p, format, args)
476 host_callback *p;
477 const char *format;
478 va_list args;
479#endif
480{
966f47b4 481 vprintf (format, args);
248c1fb8 482}
966f47b4 483
248c1fb8
JL
484/* VARARGS */
485static void
486#ifdef ANSI_PROTOTYPES
487os_evprintf_filtered (host_callback *p, const char *format, va_list args)
488#else
489os_evprintf_filtered (p, format, args)
490 host_callback *p;
491 const char *format;
492 va_list args;
493#endif
494{
495 vfprintf (stderr, format, args);
966f47b4
DE
496}
497
498/* VARARGS */
499static void
500#ifdef ANSI_PROTOTYPES
501os_error (host_callback *p, const char *format, ...)
502#else
503os_error (p, va_alist)
504 host_callback *p;
505 va_dcl
506#endif
507{
508 va_list args;
509#ifdef ANSI_PROTOTYPES
510 va_start (args, format);
511#else
512 char *format;
513
514 va_start (args);
515 format = va_arg (args, char *);
516#endif
517
518 vfprintf (stderr, format, args);
519 fprintf (stderr, "\n");
520
521 va_end (args);
c45adab0 522 exit (1);
966f47b4
DE
523}
524
525host_callback default_callback =
526{
527 os_close,
528 os_get_errno,
529 os_isatty,
530 os_lseek,
531 os_open,
532 os_read,
533 os_read_stdin,
534 os_rename,
535 os_system,
536 os_time,
537 os_unlink,
538 os_write,
539 os_write_stdout,
248c1fb8
JL
540 os_flush_stdout,
541 os_write_stderr,
542 os_flush_stderr,
543
f7abc1ca
DE
544 os_stat,
545 os_fstat,
546
248c1fb8 547 os_poll_quit,
966f47b4
DE
548
549 os_shutdown,
550 os_init,
551
f7abc1ca 552 os_printf_filtered, /* deprecated */
248c1fb8
JL
553
554 os_vprintf_filtered,
555 os_evprintf_filtered,
966f47b4
DE
556 os_error,
557
558 0, /* last errno */
248c1fb8
JL
559
560 { 0, }, /* fdmap */
561 { 0, }, /* fdopen */
562 { 0, }, /* alwaysopen */
563
f7abc1ca
DE
564 0, /* syscall_map */
565 0, /* errno_map */
566 0, /* open_map */
567 0, /* signal_map */
568 0, /* stat_map */
569
248c1fb8 570 HOST_CALLBACK_MAGIC,
966f47b4
DE
571};
572\f
f7abc1ca 573/* Read in a file describing the target's system call values.
f7abc1ca 574 E.g. maybe someone will want to use something other than newlib.
9b51b3dd
DE
575 This assumes that the basic system call recognition and value passing/
576 returning is supported. So maybe some coding/recompilation will be
577 necessary, but not as much.
f7abc1ca
DE
578
579 If an error occurs, the existing mapping is not changed. */
580
581CB_RC
582cb_read_target_syscall_maps (cb, file)
583 host_callback *cb;
584 const char *file;
585{
586 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
587 const char *stat_map;
588 FILE *f;
589
590 if ((f = fopen (file, "r")) == NULL)
591 return CB_RC_ACCESS;
592
593 /* ... read in and parse file ... */
594
595 fclose (f);
596 return CB_RC_NO_MEM; /* FIXME:wip */
597
598 /* Free storage allocated for any existing maps. */
599 if (cb->syscall_map)
600 free (cb->syscall_map);
601 if (cb->errno_map)
602 free (cb->errno_map);
603 if (cb->open_map)
604 free (cb->open_map);
605 if (cb->signal_map)
606 free (cb->signal_map);
607 if (cb->stat_map)
608 free ((PTR) cb->stat_map);
609
610 cb->syscall_map = syscall_map;
611 cb->errno_map = errno_map;
612 cb->open_map = open_map;
613 cb->signal_map = signal_map;
614 cb->stat_map = stat_map;
615
616 return CB_RC_OK;
617}
618
619/* Translate the target's version of a syscall number to the host's.
620 This isn't actually the host's version, rather a canonical form.
621 ??? Perhaps this should be renamed to ..._canon_syscall. */
966f47b4 622
f7abc1ca
DE
623int
624cb_target_to_host_syscall (cb, target_val)
625 host_callback *cb;
626 int target_val;
627{
628 CB_TARGET_DEFS_MAP *m;
629
630 for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
631 if (m->target_val == target_val)
632 return m->host_val;
633
634 return -1;
635}
966f47b4
DE
636
637/* FIXME: sort tables if large.
638 Alternatively, an obvious improvement for errno conversion is
639 to machine generate a function with a large switch(). */
640
f7abc1ca
DE
641/* Translate the host's version of errno to the target's. */
642
966f47b4 643int
f7abc1ca
DE
644cb_host_to_target_errno (cb, host_val)
645 host_callback *cb;
966f47b4
DE
646 int host_val;
647{
f7abc1ca 648 CB_TARGET_DEFS_MAP *m;
966f47b4 649
f7abc1ca 650 for (m = &cb->errno_map[0]; m->host_val; ++m)
966f47b4
DE
651 if (m->host_val == host_val)
652 return m->target_val;
653
654 /* ??? Which error to return in this case is up for grabs.
655 Note that some missing values may have standard alternatives.
656 For now return 0 and require caller to deal with it. */
657 return 0;
658}
659
660/* Given a set of target bitmasks for the open system call,
661 return the host equivalent.
662 Mapping open flag values is best done by looping so there's no need
663 to machine generate this function. */
664
665int
f7abc1ca
DE
666cb_target_to_host_open (cb, target_val)
667 host_callback *cb;
966f47b4
DE
668 int target_val;
669{
670 int host_val = 0;
f7abc1ca 671 CB_TARGET_DEFS_MAP *m;
966f47b4 672
f7abc1ca 673 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
966f47b4
DE
674 {
675 switch (m->target_val)
676 {
677 /* O_RDONLY can be (and usually is) 0 which needs to be treated
678 specially. */
679 case TARGET_O_RDONLY :
680 case TARGET_O_WRONLY :
681 case TARGET_O_RDWR :
682 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
683 == m->target_val)
684 host_val |= m->host_val;
052d7984
DE
685 /* Handle the host/target differentiating between binary and
686 text mode. Only one case is of importance */
687#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
688 host_val |= O_BINARY;
689#endif
966f47b4
DE
690 break;
691 default :
692 if ((m->target_val & target_val) == m->target_val)
693 host_val |= m->host_val;
694 break;
695 }
696 }
697
698 return host_val;
699}
f7abc1ca
DE
700
701/* Utility for cb_host_to_target_stat to store values in the target's
702 stat struct. */
703
704static void
705store (p, size, val, big_p)
706 char *p;
707 int size;
708 long val; /* ??? must be as big as target word size */
709 int big_p;
710{
711 if (big_p)
712 {
713 p += size;
714 while (size-- > 0)
715 {
716 *--p = val;
717 val >>= 8;
718 }
719 }
720 else
721 {
722 while (size-- > 0)
723 {
724 *p++ = val;
725 val >>= 8;
726 }
727 }
728}
729
730/* Translate a host's stat struct into a target's.
731
732 BIG_P is non-zero if the target is big-endian.
733 The result is the size of the target's stat struct. */
734
735int
736cb_host_to_target_stat (cb, hs, ts, big_p)
737 host_callback *cb;
738 const struct stat *hs;
739 PTR ts;
740 int big_p;
741{
742 const char *m = cb->stat_map;
743 char *p = ts;
744
745 while (m)
746 {
747 char *q = strchr (m, ',');
748 int size;
749
750 /* FIXME: Use sscanf? */
751 if (q == NULL)
752 {
753 /* FIXME: print error message */
754 return;
755 }
756 size = atoi (q + 1);
757 if (size == 0)
758 {
759 /* FIXME: print error message */
760 return;
761 }
762
763 if (strncmp (m, "st_dev", q - m) == 0)
764 store (p, size, hs->st_dev, big_p);
765 else if (strncmp (m, "st_ino", q - m) == 0)
766 store (p, size, hs->st_ino, big_p);
767 /* FIXME:wip */
768 else
769 store (p, size, 0, big_p); /* unsupported field, store 0 */
770
771 p += size;
772 m = strchr (q, ':');
773 if (m)
774 ++m;
775 }
776}
052d7984 777\f
dddbd8c5
DE
778/* Cover functions to the vfprintf callbacks.
779
780 ??? If one thinks of the callbacks as a subsystem onto itself [or part of
781 a larger "remote target subsystem"] with a well defined interface, then
782 one would think that the subsystem would provide these. However, until
783 one is allowed to create such a subsystem (with its own source tree
784 independent of any particular user), such a critter can't exist. Thus
785 these functions are here for the time being. */
052d7984
DE
786
787void
788sim_cb_printf (host_callback *p, const char *fmt, ...)
789{
790 va_list ap;
791
792 va_start (ap, fmt);
793 p->vprintf_filtered (p, fmt, ap);
794 va_end (ap);
795}
796
797void
798sim_cb_eprintf (host_callback *p, const char *fmt, ...)
799{
800 va_list ap;
801
802 va_start (ap, fmt);
803 p->evprintf_filtered (p, fmt, ap);
804 va_end (ap);
805}
This page took 0.080399 seconds and 4 git commands to generate.