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