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