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