Commit | Line | Data |
---|---|---|
c906108c | 1 | /* Remote target callback routines. |
41ee5402 DJ |
2 | Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2004 |
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" | |
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> | |
3c25f8c7 | 50 | #include "gdb/callback.h" |
c906108c SS |
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) | |
6d358e86 | 310 | host_callback *p ATTRIBUTE_UNUSED; |
c906108c SS |
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) | |
6d358e86 | 319 | host_callback *p ATTRIBUTE_UNUSED; |
c906108c SS |
320 | { |
321 | fflush (stdout); | |
322 | } | |
323 | ||
324 | static int | |
325 | os_write_stderr (p, buf, len) | |
6d358e86 | 326 | host_callback *p ATTRIBUTE_UNUSED; |
c906108c SS |
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) | |
6d358e86 | 335 | host_callback *p ATTRIBUTE_UNUSED; |
c906108c SS |
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 | ||
8822d001 JR |
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 | { | |
ee3073b5 | 424 | return wrap (p, truncate (file, len)); |
8822d001 JR |
425 | } |
426 | ||
c906108c SS |
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 | ||
5accf1ff | 463 | /* DEPRECATED */ |
c906108c SS |
464 | |
465 | /* VARARGS */ | |
466 | static void | |
467 | #ifdef ANSI_PROTOTYPES | |
6d358e86 | 468 | os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) |
c906108c SS |
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 | |
6d358e86 | 492 | os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) |
c906108c SS |
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 | |
6d358e86 | 506 | os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args) |
c906108c SS |
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 | |
6d358e86 | 520 | os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...) |
c906108c SS |
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 | ||
8822d001 JR |
566 | os_ftruncate, |
567 | os_truncate, | |
568 | ||
c906108c SS |
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, | |
6439295f | 757 | or zero if an error occurred during the translation. */ |
c906108c SS |
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 | } |