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