]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/common/callback.c
Copyright updates for 2007.
[thirdparty/binutils-gdb.git] / sim / common / callback.c
CommitLineData
c906108c 1/* Remote target callback routines.
6aba47ca 2 Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2004, 2007
41ee5402 3 Free Software Foundation, Inc.
c906108c
SS
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
41ee5402 26#include "cconfig.h"
c906108c
SS
27#endif
28#include "ansidecl.h"
c906108c 29#include <stdarg.h>
c906108c
SS
30#include <stdio.h>
31#ifdef HAVE_STDLIB_H
32#include <stdlib.h>
33#endif
34#ifdef HAVE_STRING_H
35#include <string.h>
36#else
37#ifdef HAVE_STRINGS_H
38#include <strings.h>
39#endif
40#endif
97f669ed
HPN
41#ifdef HAVE_LIMITS_H
42/* For PIPE_BUF. */
43#include <limits.h>
44#endif
c906108c
SS
45#include <errno.h>
46#include <fcntl.h>
47#include <time.h>
48#include <sys/types.h>
49#include <sys/stat.h>
3c25f8c7 50#include "gdb/callback.h"
c906108c 51#include "targ-vals.h"
97f669ed
HPN
52/* For xmalloc. */
53#include "libiberty.h"
c906108c
SS
54
55#ifdef HAVE_UNISTD_H
56#include <unistd.h>
57#endif
58
33aa0cbb
PB
59#ifndef PIPE_BUF
60#define PIPE_BUF 512
61#endif
62
c906108c
SS
63/* ??? sim_cb_printf should be cb_printf, but until the callback support is
64 broken out of the simulator directory, these are here to not require
65 sim-utils.h. */
66void sim_cb_printf PARAMS ((host_callback *, const char *, ...));
67void sim_cb_eprintf PARAMS ((host_callback *, const char *, ...));
68
69extern CB_TARGET_DEFS_MAP cb_init_syscall_map[];
70extern CB_TARGET_DEFS_MAP cb_init_errno_map[];
71extern CB_TARGET_DEFS_MAP cb_init_open_map[];
72
73extern int system PARAMS ((const char *));
74
75static int os_init PARAMS ((host_callback *));
76static int os_shutdown PARAMS ((host_callback *));
77static int os_unlink PARAMS ((host_callback *, const char *));
78static long os_time PARAMS ((host_callback *, long *));
79static int os_system PARAMS ((host_callback *, const char *));
80static int os_rename PARAMS ((host_callback *, const char *, const char *));
81static int os_write_stdout PARAMS ((host_callback *, const char *, int));
82static void os_flush_stdout PARAMS ((host_callback *));
83static int os_write_stderr PARAMS ((host_callback *, const char *, int));
84static void os_flush_stderr PARAMS ((host_callback *));
85static int os_write PARAMS ((host_callback *, int, const char *, int));
86static int os_read_stdin PARAMS ((host_callback *, char *, int));
87static int os_read PARAMS ((host_callback *, int, char *, int));
88static int os_open PARAMS ((host_callback *, const char *, int));
89static int os_lseek PARAMS ((host_callback *, int, long, int));
90static int os_isatty PARAMS ((host_callback *, int));
91static int os_get_errno PARAMS ((host_callback *));
92static int os_close PARAMS ((host_callback *, int));
93static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
94static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
95static void os_error PARAMS ((host_callback *, const char *, ...));
96static int fdmap PARAMS ((host_callback *, int));
97static int fdbad PARAMS ((host_callback *, int));
98static int wrap PARAMS ((host_callback *, int));
99
100/* Set the callback copy of errno from what we see now. */
101
102static int
103wrap (p, val)
104 host_callback *p;
105 int val;
106{
107 p->last_errno = errno;
108 return val;
109}
110
111/* Make sure the FD provided is ok. If not, return non-zero
112 and set errno. */
113
114static int
115fdbad (p, fd)
116 host_callback *p;
117 int fd;
118{
594ee3a7 119 if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
c906108c
SS
120 {
121 p->last_errno = EINVAL;
122 return -1;
123 }
124 return 0;
125}
126
127static int
128fdmap (p, fd)
129 host_callback *p;
130 int fd;
131{
132 return p->fdmap[fd];
133}
134
135static int
136os_close (p, fd)
137 host_callback *p;
138 int fd;
139{
140 int result;
594ee3a7 141 int i, next;
c906108c
SS
142
143 result = fdbad (p, fd);
144 if (result)
145 return result;
594ee3a7
JR
146 /* If this file descripter has one or more buddies (originals /
147 duplicates from a dup), just remove it from the circular list. */
148 for (i = fd; (next = p->fd_buddy[i]) != fd; )
149 i = next;
150 if (fd != i)
151 p->fd_buddy[i] = p->fd_buddy[fd];
152 else
97f669ed
HPN
153 {
154 if (p->ispipe[fd])
155 {
156 int other = p->ispipe[fd];
157 int reader, writer;
158
159 if (other > 0)
160 {
161 /* Closing the read side. */
162 reader = fd;
163 writer = other;
164 }
165 else
166 {
167 /* Closing the write side. */
168 writer = fd;
169 reader = -other;
170 }
171
172 /* If there was data in the buffer, make a last "now empty"
173 call, then deallocate data. */
174 if (p->pipe_buffer[writer].buffer != NULL)
175 {
176 (*p->pipe_empty) (p, reader, writer);
177 free (p->pipe_buffer[writer].buffer);
178 p->pipe_buffer[writer].buffer = NULL;
179 }
180
181 /* Clear pipe data for this side. */
182 p->pipe_buffer[fd].size = 0;
183 p->ispipe[fd] = 0;
184
185 /* If this was the first close, mark the other side as the
186 only remaining side. */
187 if (fd != abs (other))
188 p->ispipe[abs (other)] = -other;
189 p->fd_buddy[fd] = -1;
190 return 0;
191 }
192
193 result = wrap (p, close (fdmap (p, fd)));
194 }
594ee3a7 195 p->fd_buddy[fd] = -1;
c906108c
SS
196
197 return result;
198}
199
200
201/* taken from gdb/util.c:notice_quit() - should be in a library */
202
203
204#if defined(__GO32__) || defined (_MSC_VER)
205static int
206os_poll_quit (p)
207 host_callback *p;
208{
209#if defined(__GO32__)
210 int kbhit ();
211 int getkey ();
212 if (kbhit ())
213 {
214 int k = getkey ();
215 if (k == 1)
216 {
217 return 1;
218 }
219 else if (k == 2)
220 {
221 return 1;
222 }
223 else
224 {
225 sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
226 }
227 }
228#endif
229#if defined (_MSC_VER)
230 /* NB - this will not compile! */
231 int k = win32pollquit();
232 if (k == 1)
233 return 1;
234 else if (k == 2)
235 return 1;
236#endif
237 return 0;
238}
239#else
240#define os_poll_quit 0
241#endif /* defined(__GO32__) || defined(_MSC_VER) */
242
243static int
244os_get_errno (p)
245 host_callback *p;
246{
247 return cb_host_to_target_errno (p, p->last_errno);
248}
249
250
251static int
252os_isatty (p, fd)
253 host_callback *p;
254 int fd;
255{
256 int result;
257
258 result = fdbad (p, fd);
259 if (result)
260 return result;
261 result = wrap (p, isatty (fdmap (p, fd)));
262
263 return result;
264}
265
266static int
267os_lseek (p, fd, off, way)
268 host_callback *p;
269 int fd;
270 long off;
271 int way;
272{
273 int result;
274
275 result = fdbad (p, fd);
276 if (result)
277 return result;
278 result = lseek (fdmap (p, fd), off, way);
279 return result;
280}
281
282static int
283os_open (p, name, flags)
284 host_callback *p;
285 const char *name;
286 int flags;
287{
288 int i;
289 for (i = 0; i < MAX_CALLBACK_FDS; i++)
290 {
594ee3a7 291 if (p->fd_buddy[i] < 0)
c906108c
SS
292 {
293 int f = open (name, cb_target_to_host_open (p, flags), 0644);
294 if (f < 0)
295 {
296 p->last_errno = errno;
297 return f;
298 }
594ee3a7 299 p->fd_buddy[i] = i;
c906108c
SS
300 p->fdmap[i] = f;
301 return i;
302 }
303 }
304 p->last_errno = EMFILE;
305 return -1;
306}
307
308static int
309os_read (p, fd, buf, len)
310 host_callback *p;
311 int fd;
312 char *buf;
313 int len;
314{
315 int result;
316
317 result = fdbad (p, fd);
318 if (result)
319 return result;
97f669ed
HPN
320 if (p->ispipe[fd])
321 {
322 int writer = p->ispipe[fd];
323
324 /* Can't read from the write-end. */
325 if (writer < 0)
326 {
327 p->last_errno = EBADF;
328 return -1;
329 }
330
331 /* Nothing to read if nothing is written. */
332 if (p->pipe_buffer[writer].size == 0)
333 return 0;
334
335 /* Truncate read request size to buffer size minus what's already
336 read. */
337 if (len > p->pipe_buffer[writer].size - p->pipe_buffer[fd].size)
338 len = p->pipe_buffer[writer].size - p->pipe_buffer[fd].size;
339
340 memcpy (buf, p->pipe_buffer[writer].buffer + p->pipe_buffer[fd].size,
341 len);
342
343 /* Account for what we just read. */
344 p->pipe_buffer[fd].size += len;
345
346 /* If we've read everything, empty and deallocate the buffer and
347 signal buffer-empty to client. (This isn't expected to be a
348 hot path in the simulator, so we don't hold on to the buffer.) */
349 if (p->pipe_buffer[fd].size == p->pipe_buffer[writer].size)
350 {
351 free (p->pipe_buffer[writer].buffer);
352 p->pipe_buffer[writer].buffer = NULL;
353 p->pipe_buffer[fd].size = 0;
354 p->pipe_buffer[writer].size = 0;
355 (*p->pipe_empty) (p, fd, writer);
356 }
357
358 return len;
359 }
360
c906108c
SS
361 result = wrap (p, read (fdmap (p, fd), buf, len));
362 return result;
363}
364
365static int
366os_read_stdin (p, buf, len)
367 host_callback *p;
368 char *buf;
369 int len;
370{
371 return wrap (p, read (0, buf, len));
372}
373
374static int
375os_write (p, fd, buf, len)
376 host_callback *p;
377 int fd;
378 const char *buf;
379 int len;
380{
381 int result;
382 int real_fd;
383
384 result = fdbad (p, fd);
385 if (result)
386 return result;
97f669ed
HPN
387
388 if (p->ispipe[fd])
389 {
390 int reader = -p->ispipe[fd];
391
392 /* Can't write to the read-end. */
393 if (reader < 0)
394 {
395 p->last_errno = EBADF;
396 return -1;
397 }
398
399 /* Can't write to pipe with closed read end.
400 FIXME: We should send a SIGPIPE. */
401 if (reader == fd)
402 {
403 p->last_errno = EPIPE;
404 return -1;
405 }
406
407 /* As a sanity-check, we bail out it the buffered contents is much
408 larger than the size of the buffer on the host. We don't want
409 to run out of memory in the simulator due to a target program
410 bug if we can help it. Unfortunately, regarding the value that
411 reaches the simulated program, it's no use returning *less*
412 than the requested amount, because cb_syscall loops calling
413 this function until the whole amount is done. */
414 if (p->pipe_buffer[fd].size + len > 10 * PIPE_BUF)
415 {
416 p->last_errno = EFBIG;
417 return -1;
418 }
419
420 p->pipe_buffer[fd].buffer
421 = xrealloc (p->pipe_buffer[fd].buffer, p->pipe_buffer[fd].size + len);
422 memcpy (p->pipe_buffer[fd].buffer + p->pipe_buffer[fd].size,
423 buf, len);
424 p->pipe_buffer[fd].size += len;
425
426 (*p->pipe_nonempty) (p, reader, fd);
427 return len;
428 }
429
c906108c
SS
430 real_fd = fdmap (p, fd);
431 switch (real_fd)
432 {
433 default:
434 result = wrap (p, write (real_fd, buf, len));
435 break;
436 case 1:
437 result = p->write_stdout (p, buf, len);
438 break;
439 case 2:
440 result = p->write_stderr (p, buf, len);
441 break;
442 }
443 return result;
444}
445
446static int
447os_write_stdout (p, buf, len)
6d358e86 448 host_callback *p ATTRIBUTE_UNUSED;
c906108c
SS
449 const char *buf;
450 int len;
451{
452 return fwrite (buf, 1, len, stdout);
453}
454
455static void
456os_flush_stdout (p)
6d358e86 457 host_callback *p ATTRIBUTE_UNUSED;
c906108c
SS
458{
459 fflush (stdout);
460}
461
462static int
463os_write_stderr (p, buf, len)
6d358e86 464 host_callback *p ATTRIBUTE_UNUSED;
c906108c
SS
465 const char *buf;
466 int len;
467{
468 return fwrite (buf, 1, len, stderr);
469}
470
471static void
472os_flush_stderr (p)
6d358e86 473 host_callback *p ATTRIBUTE_UNUSED;
c906108c
SS
474{
475 fflush (stderr);
476}
477
478static int
479os_rename (p, f1, f2)
480 host_callback *p;
481 const char *f1;
482 const char *f2;
483{
484 return wrap (p, rename (f1, f2));
485}
486
487
488static int
489os_system (p, s)
490 host_callback *p;
491 const char *s;
492{
493 return wrap (p, system (s));
494}
495
496static long
497os_time (p, t)
498 host_callback *p;
499 long *t;
500{
501 return wrap (p, time (t));
502}
503
504
505static int
506os_unlink (p, f1)
507 host_callback *p;
508 const char *f1;
509{
510 return wrap (p, unlink (f1));
511}
512
513static int
514os_stat (p, file, buf)
515 host_callback *p;
516 const char *file;
517 struct stat *buf;
518{
519 /* ??? There is an issue of when to translate to the target layout.
520 One could do that inside this function, or one could have the
521 caller do it. It's more flexible to let the caller do it, though
522 I'm not sure the flexibility will ever be useful. */
523 return wrap (p, stat (file, buf));
524}
525
526static int
527os_fstat (p, fd, buf)
528 host_callback *p;
529 int fd;
530 struct stat *buf;
531{
532 if (fdbad (p, fd))
533 return -1;
97f669ed
HPN
534
535 if (p->ispipe[fd])
536 {
0c4507fd 537#if defined (HAVE_STRUCT_STAT_ST_ATIME) || defined (HAVE_STRUCT_STAT_ST_CTIME) || defined (HAVE_STRUCT_STAT_ST_MTIME)
97f669ed 538 time_t t = (*p->time) (p, NULL);
0c4507fd 539#endif
97f669ed
HPN
540
541 /* We have to fake the struct stat contents, since the pipe is
542 made up in the simulator. */
543 memset (buf, 0, sizeof (*buf));
544
545#ifdef HAVE_STRUCT_STAT_ST_MODE
546 buf->st_mode = S_IFIFO;
547#endif
548
549 /* If more accurate tracking than current-time is needed (for
550 example, on GNU/Linux we get accurate numbers), the p->time
551 callback (which may be something other than os_time) should
552 happen for each read and write, and we'd need to keep track of
553 atime, ctime and mtime. */
554#ifdef HAVE_STRUCT_STAT_ST_ATIME
555 buf->st_atime = t;
556#endif
557#ifdef HAVE_STRUCT_STAT_ST_CTIME
558 buf->st_ctime = t;
559#endif
560#ifdef HAVE_STRUCT_STAT_ST_MTIME
561 buf->st_mtime = t;
562#endif
563 return 0;
564 }
565
c906108c
SS
566 /* ??? There is an issue of when to translate to the target layout.
567 One could do that inside this function, or one could have the
568 caller do it. It's more flexible to let the caller do it, though
569 I'm not sure the flexibility will ever be useful. */
570 return wrap (p, fstat (fdmap (p, fd), buf));
571}
572
0d3cd463
HPN
573static int
574os_lstat (p, file, buf)
575 host_callback *p;
576 const char *file;
577 struct stat *buf;
578{
579 /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat. */
33aa0cbb 580#ifdef HAVE_LSTAT
0d3cd463 581 return wrap (p, lstat (file, buf));
33aa0cbb
PB
582#else
583 return wrap (p, stat (file, buf));
584#endif
0d3cd463
HPN
585}
586
8822d001
JR
587static int
588os_ftruncate (p, fd, len)
589 host_callback *p;
590 int fd;
591 long len;
592{
593 int result;
594
595 result = fdbad (p, fd);
97f669ed
HPN
596 if (p->ispipe[fd])
597 {
598 p->last_errno = EINVAL;
599 return -1;
600 }
8822d001
JR
601 if (result)
602 return result;
33aa0cbb 603#ifdef HAVE_FTRUNCATE
8822d001 604 result = wrap (p, ftruncate (fdmap (p, fd), len));
33aa0cbb
PB
605#else
606 p->last_errno = EINVAL;
607 result = -1;
608#endif
8822d001
JR
609 return result;
610}
611
612static int
613os_truncate (p, file, len)
614 host_callback *p;
615 const char *file;
616 long len;
617{
33aa0cbb 618#ifdef HAVE_TRUNCATE
ee3073b5 619 return wrap (p, truncate (file, len));
33aa0cbb
PB
620#else
621 p->last_errno = EINVAL;
622 return -1;
623#endif
8822d001
JR
624}
625
97f669ed
HPN
626static int
627os_pipe (p, filedes)
628 host_callback *p;
629 int *filedes;
630{
631 int i;
632
633 /* We deliberately don't use fd 0. It's probably stdin anyway. */
634 for (i = 1; i < MAX_CALLBACK_FDS; i++)
635 {
636 int j;
637
638 if (p->fd_buddy[i] < 0)
639 for (j = i + 1; j < MAX_CALLBACK_FDS; j++)
640 if (p->fd_buddy[j] < 0)
641 {
642 /* Found two free fd:s. Set stat to allocated and mark
643 pipeness. */
644 p->fd_buddy[i] = i;
645 p->fd_buddy[j] = j;
646 p->ispipe[i] = j;
647 p->ispipe[j] = -i;
648 filedes[0] = i;
649 filedes[1] = j;
650
651 /* Poison the FD map to make bugs apparent. */
652 p->fdmap[i] = -1;
653 p->fdmap[j] = -1;
654 return 0;
655 }
656 }
657
658 p->last_errno = EMFILE;
659 return -1;
660}
661
662/* Stub functions for pipe support. They should always be overridden in
663 targets using the pipe support, but that's up to the target. */
664
665/* Called when the simulator says that the pipe at (reader, writer) is
666 now empty (so the writer should leave its waiting state). */
667
668static void
669os_pipe_empty (p, reader, writer)
670 host_callback *p;
671 int reader;
672 int writer;
673{
674}
675
676/* Called when the simulator says the pipe at (reader, writer) is now
677 non-empty (so the writer should wait). */
678
679static void
680os_pipe_nonempty (p, reader, writer)
681 host_callback *p;
682 int reader;
683 int writer;
684{
685}
686
c906108c
SS
687static int
688os_shutdown (p)
689 host_callback *p;
690{
594ee3a7 691 int i, next, j;
c906108c
SS
692 for (i = 0; i < MAX_CALLBACK_FDS; i++)
693 {
594ee3a7
JR
694 int do_close = 1;
695
97f669ed
HPN
696 /* Zero out all pipe state. Don't call callbacks for non-empty
697 pipes; the target program has likely terminated at this point
698 or we're called at initialization time. */
699 p->ispipe[i] = 0;
700 p->pipe_buffer[i].size = 0;
701 p->pipe_buffer[i].buffer = NULL;
702
594ee3a7
JR
703 next = p->fd_buddy[i];
704 if (next < 0)
705 continue;
706 do
707 {
708 j = next;
709 if (j == MAX_CALLBACK_FDS)
710 do_close = 0;
711 next = p->fd_buddy[j];
712 p->fd_buddy[j] = -1;
713 /* At the initial call of os_init, we got -1, 0, 0, 0, ... */
714 if (next < 0)
715 {
0242f9ea 716 p->fd_buddy[i] = -1;
594ee3a7
JR
717 do_close = 0;
718 break;
719 }
720 }
721 while (j != i);
722 if (do_close)
c906108c 723 close (p->fdmap[i]);
c906108c
SS
724 }
725 return 1;
726}
727
728static int
729os_init (p)
730 host_callback *p;
731{
732 int i;
733
734 os_shutdown (p);
735 for (i = 0; i < 3; i++)
736 {
737 p->fdmap[i] = i;
594ee3a7 738 p->fd_buddy[i] = i - 1;
c906108c 739 }
594ee3a7
JR
740 p->fd_buddy[0] = MAX_CALLBACK_FDS;
741 p->fd_buddy[MAX_CALLBACK_FDS] = 2;
c906108c
SS
742
743 p->syscall_map = cb_init_syscall_map;
744 p->errno_map = cb_init_errno_map;
745 p->open_map = cb_init_open_map;
746
747 return 1;
748}
749
5accf1ff 750/* DEPRECATED */
c906108c
SS
751
752/* VARARGS */
753static void
6d358e86 754os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
755{
756 va_list args;
c906108c 757 va_start (args, format);
c906108c
SS
758
759 vfprintf (stdout, format, args);
760 va_end (args);
761}
762
763/* VARARGS */
764static void
6d358e86 765os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
766{
767 vprintf (format, args);
768}
769
770/* VARARGS */
771static void
6d358e86 772os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
c906108c
SS
773{
774 vfprintf (stderr, format, args);
775}
776
777/* VARARGS */
778static void
6d358e86 779os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
c906108c
SS
780{
781 va_list args;
c906108c 782 va_start (args, format);
c906108c
SS
783
784 vfprintf (stderr, format, args);
785 fprintf (stderr, "\n");
786
787 va_end (args);
788 exit (1);
789}
790
791host_callback default_callback =
792{
793 os_close,
794 os_get_errno,
795 os_isatty,
796 os_lseek,
797 os_open,
798 os_read,
799 os_read_stdin,
800 os_rename,
801 os_system,
802 os_time,
803 os_unlink,
804 os_write,
805 os_write_stdout,
806 os_flush_stdout,
807 os_write_stderr,
808 os_flush_stderr,
809
810 os_stat,
811 os_fstat,
0d3cd463 812 os_lstat,
c906108c 813
8822d001
JR
814 os_ftruncate,
815 os_truncate,
816
97f669ed
HPN
817 os_pipe,
818 os_pipe_empty,
819 os_pipe_nonempty,
820
c906108c
SS
821 os_poll_quit,
822
823 os_shutdown,
824 os_init,
825
826 os_printf_filtered, /* deprecated */
827
828 os_vprintf_filtered,
829 os_evprintf_filtered,
830 os_error,
831
832 0, /* last errno */
833
834 { 0, }, /* fdmap */
594ee3a7 835 { -1, }, /* fd_buddy */
97f669ed
HPN
836 { 0, }, /* ispipe */
837 { { 0, 0 }, }, /* pipe_buffer */
c906108c
SS
838
839 0, /* syscall_map */
840 0, /* errno_map */
841 0, /* open_map */
842 0, /* signal_map */
843 0, /* stat_map */
844
f4f8cce4
HPN
845 /* Defaults expected to be overridden at initialization, where needed. */
846 BFD_ENDIAN_UNKNOWN, /* target_endian */
97f669ed 847 4, /* target_sizeof_int */
f4f8cce4 848
c906108c
SS
849 HOST_CALLBACK_MAGIC,
850};
851\f
852/* Read in a file describing the target's system call values.
853 E.g. maybe someone will want to use something other than newlib.
854 This assumes that the basic system call recognition and value passing/
855 returning is supported. So maybe some coding/recompilation will be
856 necessary, but not as much.
857
858 If an error occurs, the existing mapping is not changed. */
859
860CB_RC
861cb_read_target_syscall_maps (cb, file)
862 host_callback *cb;
863 const char *file;
864{
865 CB_TARGET_DEFS_MAP *syscall_map, *errno_map, *open_map, *signal_map;
866 const char *stat_map;
867 FILE *f;
868
869 if ((f = fopen (file, "r")) == NULL)
870 return CB_RC_ACCESS;
871
872 /* ... read in and parse file ... */
873
874 fclose (f);
875 return CB_RC_NO_MEM; /* FIXME:wip */
876
877 /* Free storage allocated for any existing maps. */
878 if (cb->syscall_map)
879 free (cb->syscall_map);
880 if (cb->errno_map)
881 free (cb->errno_map);
882 if (cb->open_map)
883 free (cb->open_map);
884 if (cb->signal_map)
885 free (cb->signal_map);
886 if (cb->stat_map)
887 free ((PTR) cb->stat_map);
888
889 cb->syscall_map = syscall_map;
890 cb->errno_map = errno_map;
891 cb->open_map = open_map;
892 cb->signal_map = signal_map;
893 cb->stat_map = stat_map;
894
895 return CB_RC_OK;
896}
897
898/* Translate the target's version of a syscall number to the host's.
899 This isn't actually the host's version, rather a canonical form.
900 ??? Perhaps this should be renamed to ..._canon_syscall. */
901
902int
903cb_target_to_host_syscall (cb, target_val)
904 host_callback *cb;
905 int target_val;
906{
907 CB_TARGET_DEFS_MAP *m;
908
909 for (m = &cb->syscall_map[0]; m->target_val != -1; ++m)
910 if (m->target_val == target_val)
911 return m->host_val;
912
913 return -1;
914}
915
916/* FIXME: sort tables if large.
917 Alternatively, an obvious improvement for errno conversion is
918 to machine generate a function with a large switch(). */
919
920/* Translate the host's version of errno to the target's. */
921
922int
923cb_host_to_target_errno (cb, host_val)
924 host_callback *cb;
925 int host_val;
926{
927 CB_TARGET_DEFS_MAP *m;
928
929 for (m = &cb->errno_map[0]; m->host_val; ++m)
930 if (m->host_val == host_val)
931 return m->target_val;
932
933 /* ??? Which error to return in this case is up for grabs.
934 Note that some missing values may have standard alternatives.
935 For now return 0 and require caller to deal with it. */
936 return 0;
937}
938
939/* Given a set of target bitmasks for the open system call,
940 return the host equivalent.
941 Mapping open flag values is best done by looping so there's no need
942 to machine generate this function. */
943
944int
945cb_target_to_host_open (cb, target_val)
946 host_callback *cb;
947 int target_val;
948{
949 int host_val = 0;
950 CB_TARGET_DEFS_MAP *m;
951
952 for (m = &cb->open_map[0]; m->host_val != -1; ++m)
953 {
954 switch (m->target_val)
955 {
956 /* O_RDONLY can be (and usually is) 0 which needs to be treated
957 specially. */
958 case TARGET_O_RDONLY :
959 case TARGET_O_WRONLY :
960 case TARGET_O_RDWR :
961 if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
962 == m->target_val)
963 host_val |= m->host_val;
964 /* Handle the host/target differentiating between binary and
965 text mode. Only one case is of importance */
966#if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
967 host_val |= O_BINARY;
968#endif
969 break;
970 default :
971 if ((m->target_val & target_val) == m->target_val)
972 host_val |= m->host_val;
973 break;
974 }
975 }
976
977 return host_val;
978}
979
f4f8cce4 980/* Utility for e.g. cb_host_to_target_stat to store values in the target's
c906108c
SS
981 stat struct. */
982
f4f8cce4
HPN
983void
984cb_store_target_endian (cb, p, size, val)
985 host_callback *cb;
c906108c
SS
986 char *p;
987 int size;
988 long val; /* ??? must be as big as target word size */
c906108c 989{
f4f8cce4 990 if (cb->target_endian == BFD_ENDIAN_BIG)
c906108c
SS
991 {
992 p += size;
993 while (size-- > 0)
994 {
995 *--p = val;
996 val >>= 8;
997 }
998 }
999 else
1000 {
1001 while (size-- > 0)
1002 {
1003 *p++ = val;
1004 val >>= 8;
1005 }
1006 }
1007}
1008
1009/* Translate a host's stat struct into a target's.
1010 If HS is NULL, just compute the length of the buffer required,
1011 TS is ignored.
1012
1013 The result is the size of the target's stat struct,
6439295f 1014 or zero if an error occurred during the translation. */
c906108c
SS
1015
1016int
1017cb_host_to_target_stat (cb, hs, ts)
1018 host_callback *cb;
1019 const struct stat *hs;
1020 PTR ts;
1021{
1022 const char *m = cb->stat_map;
1023 char *p;
c906108c
SS
1024
1025 if (hs == NULL)
1026 ts = NULL;
1027 p = ts;
1028
1029 while (m)
1030 {
1031 char *q = strchr (m, ',');
1032 int size;
1033
1034 /* FIXME: Use sscanf? */
1035 if (q == NULL)
1036 {
1037 /* FIXME: print error message */
1038 return 0;
1039 }
1040 size = atoi (q + 1);
1041 if (size == 0)
1042 {
1043 /* FIXME: print error message */
1044 return 0;
1045 }
1046
1047 if (hs != NULL)
1048 {
e1591da4 1049 if (0)
697afb65
HPN
1050 ;
1051 /* Defined here to avoid emacs indigestion on a lone "else". */
1052#undef ST_x
1053#define ST_x(FLD) \
1054 else if (strncmp (m, #FLD, q - m) == 0) \
f4f8cce4 1055 cb_store_target_endian (cb, p, size, hs->FLD)
697afb65
HPN
1056
1057#ifdef HAVE_STRUCT_STAT_ST_DEV
1058 ST_x (st_dev);
1059#endif
1060#ifdef HAVE_STRUCT_STAT_ST_INO
1061 ST_x (st_ino);
1062#endif
1063#ifdef HAVE_STRUCT_STAT_ST_MODE
1064 ST_x (st_mode);
1065#endif
1066#ifdef HAVE_STRUCT_STAT_ST_NLINK
1067 ST_x (st_nlink);
1068#endif
1069#ifdef HAVE_STRUCT_STAT_ST_UID
1070 ST_x (st_uid);
1071#endif
1072#ifdef HAVE_STRUCT_STAT_ST_GID
1073 ST_x (st_gid);
1074#endif
1075#ifdef HAVE_STRUCT_STAT_ST_RDEV
1076 ST_x (st_rdev);
1077#endif
1078#ifdef HAVE_STRUCT_STAT_ST_SIZE
1079 ST_x (st_size);
1080#endif
1081#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
1082 ST_x (st_blksize);
1083#endif
1084#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
1085 ST_x (st_blocks);
1086#endif
1087#ifdef HAVE_STRUCT_STAT_ST_ATIME
1088 ST_x (st_atime);
1089#endif
1090#ifdef HAVE_STRUCT_STAT_ST_MTIME
1091 ST_x (st_mtime);
1092#endif
1093#ifdef HAVE_STRUCT_STAT_ST_CTIME
1094 ST_x (st_ctime);
1095#endif
1096#undef ST_x
c906108c
SS
1097 /* FIXME:wip */
1098 else
f4f8cce4
HPN
1099 /* Unsupported field, store 0. */
1100 cb_store_target_endian (cb, p, size, 0);
c906108c
SS
1101 }
1102
1103 p += size;
1104 m = strchr (q, ':');
1105 if (m)
1106 ++m;
1107 }
1108
1109 return p - (char *) ts;
1110}
1111\f
1112/* Cover functions to the vfprintf callbacks.
1113
1114 ??? If one thinks of the callbacks as a subsystem onto itself [or part of
1115 a larger "remote target subsystem"] with a well defined interface, then
1116 one would think that the subsystem would provide these. However, until
1117 one is allowed to create such a subsystem (with its own source tree
1118 independent of any particular user), such a critter can't exist. Thus
1119 these functions are here for the time being. */
1120
1121void
1122sim_cb_printf (host_callback *p, const char *fmt, ...)
1123{
1124 va_list ap;
1125
1126 va_start (ap, fmt);
1127 p->vprintf_filtered (p, fmt, ap);
1128 va_end (ap);
1129}
1130
1131void
1132sim_cb_eprintf (host_callback *p, const char *fmt, ...)
1133{
1134 va_list ap;
1135
1136 va_start (ap, fmt);
1137 p->evprintf_filtered (p, fmt, ap);
1138 va_end (ap);
1139}