2003-10-21 Andrew Cagney <cagney@redhat.com>
[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 "gdb/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 ATTRIBUTE_UNUSED;
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 ATTRIBUTE_UNUSED;
319 {
320 fflush (stdout);
321 }
322
323 static int
324 os_write_stderr (p, buf, len)
325 host_callback *p ATTRIBUTE_UNUSED;
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 ATTRIBUTE_UNUSED;
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_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
417 static int
418 os_truncate (p, file, len)
419 host_callback *p;
420 const char *file;
421 long len;
422 {
423 return wrap (p, truncate (file, len));
424 }
425
426 static int
427 os_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
441 static int
442 os_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
462 /* DEPRECATED */
463
464 /* VARARGS */
465 static void
466 #ifdef ANSI_PROTOTYPES
467 os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
468 #else
469 os_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 */
489 static void
490 #ifdef ANSI_PROTOTYPES
491 os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
492 #else
493 os_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 */
503 static void
504 #ifdef ANSI_PROTOTYPES
505 os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
506 #else
507 os_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 */
517 static void
518 #ifdef ANSI_PROTOTYPES
519 os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
520 #else
521 os_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
543 host_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
565 os_ftruncate,
566 os_truncate,
567
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
602 CB_RC
603 cb_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
644 int
645 cb_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
664 int
665 cb_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
686 int
687 cb_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
725 static void
726 store (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,
756 or zero if an error occurred during the translation. */
757
758 int
759 cb_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
819 void
820 sim_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
829 void
830 sim_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.086294 seconds and 5 git commands to generate.