Initial creation of sourceware repository
[deliverable/binutils-gdb.git] / sim / common / callback.c
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>
49 #include "callback.h"
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. */
59 void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
60 void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
61
62 extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
63 extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
64 extern CB_TARGET_DEFS_MAP cb_init_open_map[];
65
66 extern int system PARAMS ((const char *));
67
68 static int os_init PARAMS ((host_callback *));
69 static int os_shutdown PARAMS ((host_callback *));
70 static int os_unlink PARAMS ((host_callback *, const char *));
71 static long os_time PARAMS ((host_callback *, long *));
72 static int os_system PARAMS ((host_callback *, const char *));
73 static int os_rename PARAMS ((host_callback *, const char *, const char *));
74 static int os_write_stdout PARAMS ((host_callback *, const char *, int));
75 static void os_flush_stdout PARAMS ((host_callback *));
76 static int os_write_stderr PARAMS ((host_callback *, const char *, int));
77 static void os_flush_stderr PARAMS ((host_callback *));
78 static int os_write PARAMS ((host_callback *, int, const char *, int));
79 static int os_read_stdin PARAMS ((host_callback *, char *, int));
80 static int os_read PARAMS ((host_callback *, int, char *, int));
81 static int os_open PARAMS ((host_callback *, const char *, int));
82 static int os_lseek PARAMS ((host_callback *, int, long, int));
83 static int os_isatty PARAMS ((host_callback *, int));
84 static int os_get_errno PARAMS ((host_callback *));
85 static int os_close PARAMS ((host_callback *, int));
86 static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
87 static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
88 static void os_error PARAMS ((host_callback *, const char *, ...));
89 static int fdmap PARAMS ((host_callback *, int));
90 static int fdbad PARAMS ((host_callback *, int));
91 static int wrap PARAMS ((host_callback *, int));
92
93 /* Set the callback copy of errno from what we see now. */
94
95 static int
96 wrap (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
107 static int
108 fdbad (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
120 static int
121 fdmap (p, fd)
122 host_callback *p;
123 int fd;
124 {
125 return p->fdmap[fd];
126 }
127
128 static int
129 os_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)
150 static int
151 os_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
188 static int
189 os_get_errno (p)
190 host_callback *p;
191 {
192 return cb_host_to_target_errno (p, p->last_errno);
193 }
194
195
196 static int
197 os_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
211 static int
212 os_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
227 static int
228 os_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
253 static int
254 os_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
269 static int
270 os_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
278 static int
279 os_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
307 static int
308 os_write_stdout (p, buf, len)
309 host_callback *p;
310 const char *buf;
311 int len;
312 {
313 return fwrite (buf, 1, len, stdout);
314 }
315
316 static void
317 os_flush_stdout (p)
318 host_callback *p;
319 {
320 fflush (stdout);
321 }
322
323 static int
324 os_write_stderr (p, buf, len)
325 host_callback *p;
326 const char *buf;
327 int len;
328 {
329 return fwrite (buf, 1, len, stderr);
330 }
331
332 static void
333 os_flush_stderr (p)
334 host_callback *p;
335 {
336 fflush (stderr);
337 }
338
339 static int
340 os_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
349 static int
350 os_system (p, s)
351 host_callback *p;
352 const char *s;
353 {
354 return wrap (p, system (s));
355 }
356
357 static long
358 os_time (p, t)
359 host_callback *p;
360 long *t;
361 {
362 return wrap (p, time (t));
363 }
364
365
366 static int
367 os_unlink (p, f1)
368 host_callback *p;
369 const char *f1;
370 {
371 return wrap (p, unlink (f1));
372 }
373
374 static int
375 os_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
387 static int
388 os_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
402 static int
403 os_shutdown (p)
404 host_callback *p;
405 {
406 int i;
407 for (i = 0; i < MAX_CALLBACK_FDS; i++)
408 {
409 if (p->fdopen[i] && !p->alwaysopen[i]) {
410 close (p->fdmap[i]);
411 p->fdopen[i] = 0;
412 }
413 }
414 return 1;
415 }
416
417 static int
418 os_init (p)
419 host_callback *p;
420 {
421 int i;
422
423 os_shutdown (p);
424 for (i = 0; i < 3; i++)
425 {
426 p->fdmap[i] = i;
427 p->fdopen[i] = 1;
428 p->alwaysopen[i] = 1;
429 }
430
431 p->syscall_map = cb_init_syscall_map;
432 p->errno_map = cb_init_errno_map;
433 p->open_map = cb_init_open_map;
434
435 return 1;
436 }
437
438 /* DEPRECIATED */
439
440 /* VARARGS */
441 static void
442 #ifdef ANSI_PROTOTYPES
443 os_printf_filtered (host_callback *p, const char *format, ...)
444 #else
445 os_printf_filtered (p, va_alist)
446 host_callback *p;
447 va_dcl
448 #endif
449 {
450 va_list args;
451 #ifdef ANSI_PROTOTYPES
452 va_start (args, format);
453 #else
454 char *format;
455
456 va_start (args);
457 format = va_arg (args, char *);
458 #endif
459
460 vfprintf (stdout, format, args);
461 va_end (args);
462 }
463
464 /* VARARGS */
465 static void
466 #ifdef ANSI_PROTOTYPES
467 os_vprintf_filtered (host_callback *p, const char *format, va_list args)
468 #else
469 os_vprintf_filtered (p, format, args)
470 host_callback *p;
471 const char *format;
472 va_list args;
473 #endif
474 {
475 vprintf (format, args);
476 }
477
478 /* VARARGS */
479 static void
480 #ifdef ANSI_PROTOTYPES
481 os_evprintf_filtered (host_callback *p, const char *format, va_list args)
482 #else
483 os_evprintf_filtered (p, format, args)
484 host_callback *p;
485 const char *format;
486 va_list args;
487 #endif
488 {
489 vfprintf (stderr, format, args);
490 }
491
492 /* VARARGS */
493 static void
494 #ifdef ANSI_PROTOTYPES
495 os_error (host_callback *p, const char *format, ...)
496 #else
497 os_error (p, va_alist)
498 host_callback *p;
499 va_dcl
500 #endif
501 {
502 va_list args;
503 #ifdef ANSI_PROTOTYPES
504 va_start (args, format);
505 #else
506 char *format;
507
508 va_start (args);
509 format = va_arg (args, char *);
510 #endif
511
512 vfprintf (stderr, format, args);
513 fprintf (stderr, "\n");
514
515 va_end (args);
516 exit (1);
517 }
518
519 host_callback default_callback =
520 {
521 os_close,
522 os_get_errno,
523 os_isatty,
524 os_lseek,
525 os_open,
526 os_read,
527 os_read_stdin,
528 os_rename,
529 os_system,
530 os_time,
531 os_unlink,
532 os_write,
533 os_write_stdout,
534 os_flush_stdout,
535 os_write_stderr,
536 os_flush_stderr,
537
538 os_stat,
539 os_fstat,
540
541 os_poll_quit,
542
543 os_shutdown,
544 os_init,
545
546 os_printf_filtered, /* deprecated */
547
548 os_vprintf_filtered,
549 os_evprintf_filtered,
550 os_error,
551
552 0, /* last errno */
553
554 { 0, }, /* fdmap */
555 { 0, }, /* fdopen */
556 { 0, }, /* alwaysopen */
557
558 0, /* syscall_map */
559 0, /* errno_map */
560 0, /* open_map */
561 0, /* signal_map */
562 0, /* stat_map */
563
564 HOST_CALLBACK_MAGIC,
565 };
566 \f
567 /* Read in a file describing the target's system call values.
568 E.g. maybe someone will want to use something other than newlib.
569 This assumes that the basic system call recognition and value passing/
570 returning is supported. So maybe some coding/recompilation will be
571 necessary, but not as much.
572
573 If an error occurs, the existing mapping is not changed. */
574
575 CB_RC
576 cb_read_target_syscall_maps (cb, file)
577 host_callback *cb;
578 const char *file;
579 {
580 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
581 const char *stat_map;
582 FILE *f;
583
584 if ((f = fopen (file, "r")) == NULL)
585 return CB_RC_ACCESS;
586
587 /* ... read in and parse file ... */
588
589 fclose (f);
590 return CB_RC_NO_MEM; /* FIXME:wip */
591
592 /* Free storage allocated for any existing maps. */
593 if (cb->syscall_map)
594 free (cb->syscall_map);
595 if (cb->errno_map)
596 free (cb->errno_map);
597 if (cb->open_map)
598 free (cb->open_map);
599 if (cb->signal_map)
600 free (cb->signal_map);
601 if (cb->stat_map)
602 free ((PTR) cb->stat_map);
603
604 cb->syscall_map = syscall_map;
605 cb->errno_map = errno_map;
606 cb->open_map = open_map;
607 cb->signal_map = signal_map;
608 cb->stat_map = stat_map;
609
610 return CB_RC_OK;
611 }
612
613 /* Translate the target's version of a syscall number to the host's.
614 This isn't actually the host's version, rather a canonical form.
615 ??? Perhaps this should be renamed to ..._canon_syscall. */
616
617 int
618 cb_target_to_host_syscall (cb, target_val)
619 host_callback *cb;
620 int target_val;
621 {
622 CB_TARGET_DEFS_MAP *m;
623
624 for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
625 if (m->target_val == target_val)
626 return m->host_val;
627
628 return -1;
629 }
630
631 /* FIXME: sort tables if large.
632 Alternatively, an obvious improvement for errno conversion is
633 to machine generate a function with a large switch(). */
634
635 /* Translate the host's version of errno to the target's. */
636
637 int
638 cb_host_to_target_errno (cb, host_val)
639 host_callback *cb;
640 int host_val;
641 {
642 CB_TARGET_DEFS_MAP *m;
643
644 for (m = &cb->errno_map[0]; m->host_val; ++m)
645 if (m->host_val == host_val)
646 return m->target_val;
647
648 /* ??? Which error to return in this case is up for grabs.
649 Note that some missing values may have standard alternatives.
650 For now return 0 and require caller to deal with it. */
651 return 0;
652 }
653
654 /* Given a set of target bitmasks for the open system call,
655 return the host equivalent.
656 Mapping open flag values is best done by looping so there's no need
657 to machine generate this function. */
658
659 int
660 cb_target_to_host_open (cb, target_val)
661 host_callback *cb;
662 int target_val;
663 {
664 int host_val = 0;
665 CB_TARGET_DEFS_MAP *m;
666
667 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
668 {
669 switch (m->target_val)
670 {
671 /* O_RDONLY can be (and usually is) 0 which needs to be treated
672 specially. */
673 case TARGET_O_RDONLY :
674 case TARGET_O_WRONLY :
675 case TARGET_O_RDWR :
676 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
677 == m->target_val)
678 host_val |= m->host_val;
679 /* Handle the host/target differentiating between binary and
680 text mode. Only one case is of importance */
681 #if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
682 host_val |= O_BINARY;
683 #endif
684 break;
685 default :
686 if ((m->target_val & target_val) == m->target_val)
687 host_val |= m->host_val;
688 break;
689 }
690 }
691
692 return host_val;
693 }
694
695 /* Utility for cb_host_to_target_stat to store values in the target's
696 stat struct. */
697
698 static void
699 store (p, size, val, big_p)
700 char *p;
701 int size;
702 long val; /* ??? must be as big as target word size */
703 int big_p;
704 {
705 if (big_p)
706 {
707 p += size;
708 while (size-- > 0)
709 {
710 *--p = val;
711 val >>= 8;
712 }
713 }
714 else
715 {
716 while (size-- > 0)
717 {
718 *p++ = val;
719 val >>= 8;
720 }
721 }
722 }
723
724 /* Translate a host's stat struct into a target's.
725 If HS is NULL, just compute the length of the buffer required,
726 TS is ignored.
727
728 The result is the size of the target's stat struct,
729 or zero if an error occured during the translation. */
730
731 int
732 cb_host_to_target_stat (cb, hs, ts)
733 host_callback *cb;
734 const struct stat *hs;
735 PTR ts;
736 {
737 const char *m = cb->stat_map;
738 char *p;
739 int big_p = 0;
740
741 if (hs == NULL)
742 ts = NULL;
743 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 0;
755 }
756 size = atoi (q + 1);
757 if (size == 0)
758 {
759 /* FIXME: print error message */
760 return 0;
761 }
762
763 if (hs != NULL)
764 {
765 if (strncmp (m, "st_dev", q - m) == 0)
766 store (p, size, hs->st_dev, big_p);
767 else if (strncmp (m, "st_ino", q - m) == 0)
768 store (p, size, hs->st_ino, big_p);
769 /* FIXME:wip */
770 else
771 store (p, size, 0, big_p); /* unsupported field, store 0 */
772 }
773
774 p += size;
775 m = strchr (q, ':');
776 if (m)
777 ++m;
778 }
779
780 return p - (char *) ts;
781 }
782 \f
783 /* Cover functions to the vfprintf callbacks.
784
785 ??? If one thinks of the callbacks as a subsystem onto itself [or part of
786 a larger "remote target subsystem"] with a well defined interface, then
787 one would think that the subsystem would provide these. However, until
788 one is allowed to create such a subsystem (with its own source tree
789 independent of any particular user), such a critter can't exist. Thus
790 these functions are here for the time being. */
791
792 void
793 sim_cb_printf (host_callback *p, const char *fmt, ...)
794 {
795 va_list ap;
796
797 va_start (ap, fmt);
798 p->vprintf_filtered (p, fmt, ap);
799 va_end (ap);
800 }
801
802 void
803 sim_cb_eprintf (host_callback *p, const char *fmt, ...)
804 {
805 va_list ap;
806
807 va_start (ap, fmt);
808 p->evprintf_filtered (p, fmt, ap);
809 va_end (ap);
810 }
This page took 0.047398 seconds and 4 git commands to generate.