Tweak comment.
[external/binutils.git] / sim / common / callback.c
1 /* Remote target callback routines.
2    Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Cygnus Solutions.
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
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.  */
20
21 /* This file provides a standard way for targets to talk to the host OS
22    level.  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
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
37 #ifdef HAVE_STRING_H
38 #include <string.h>
39 #else
40 #ifdef HAVE_STRINGS_H
41 #include <strings.h>
42 #endif
43 #endif
44 #include <errno.h>
45 #include <fcntl.h>
46 #include <time.h>
47 #include <sys/types.h>
48 #include <sys/stat.h>
49 #include "callback.h"
50 #include "targ-vals.h"
51
52 #ifdef HAVE_UNISTD_H
53 #include <unistd.h>
54 #endif
55
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
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
66 extern int system PARAMS ((const char *));
67
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));
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 *));
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));
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 *, ...));
89 static int fdmap PARAMS ((host_callback *, int));
90 static int fdbad PARAMS ((host_callback *, int));
91 static int wrap PARAMS ((host_callback *, int));
92 static int enosys 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 /* 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
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)));
155   if(result == 0 && !p->alwaysopen[fd])
156     p->fdopen[fd] = 0;
157
158   return result;
159 }
160
161
162 /* taken from gdb/util.c:notice_quit() - should be in a library */
163
164
165 #if defined(__GO32__) || defined (_MSC_VER)
166 static int
167 os_poll_quit (p)
168      host_callback *p;
169 {
170 #if defined(__GO32__)
171   int kbhit ();
172   int getkey ();
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         {
186           sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
187         }
188     }
189 #endif
190 #if defined (_MSC_VER)
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;
197 #endif
198   return 0;
199 }
200 #else
201 #define os_poll_quit 0
202 #endif /* defined(__GO32__) || defined(_MSC_VER) */
203
204 static int 
205 os_get_errno (p)
206      host_callback *p;
207 {
208   return cb_host_to_target_errno (p, p->last_errno);
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)));
223
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;
247      int flags;
248 {
249   int i;
250   for (i = 0; i < MAX_CALLBACK_FDS; i++)
251     {
252       if (!p->fdopen[i])
253         {
254           int f = open (name, cb_target_to_host_open (p, flags), 0644);
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;
302   int real_fd;
303
304   result = fdbad (p, fd);
305   if (result)
306     return result;
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     }
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 {
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);
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
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 }
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
424 os_init (p)
425      host_callback *p;
426 {
427   int i;
428
429   os_shutdown (p);
430   for (i = 0; i < 3; i++)
431     {
432       p->fdmap[i] = i;
433       p->fdopen[i] = 1;
434       p->alwaysopen[i] = 1;
435     }
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
441   return 1;
442 }
443
444 /* DEPRECIATED */
445
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
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 {
481   vprintf (format, args);
482 }
483
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);
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);
522   exit (1);
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,
540   os_flush_stdout,
541   os_write_stderr,
542   os_flush_stderr,
543
544   os_stat,
545   os_fstat,
546
547   os_poll_quit,
548
549   os_shutdown,
550   os_init,
551
552   os_printf_filtered,  /* deprecated */
553
554   os_vprintf_filtered,
555   os_evprintf_filtered,
556   os_error,
557
558   0,            /* last errno */
559
560   { 0, },       /* fdmap */
561   { 0, },       /* fdopen */
562   { 0, },       /* alwaysopen */
563
564   0, /* syscall_map */
565   0, /* errno_map */
566   0, /* open_map */
567   0, /* signal_map */
568   0, /* stat_map */
569         
570   HOST_CALLBACK_MAGIC,
571 };
572 \f
573 /* Read in a file describing the target's system call values.
574    E.g. maybe someone will want to use something other than newlib.
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.
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.  */
622
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 }
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
641 /* Translate the host's version of errno to the target's.  */
642
643 int
644 cb_host_to_target_errno (cb, host_val)
645      host_callback *cb;
646      int host_val;
647 {
648   CB_TARGET_DEFS_MAP *m;
649
650   for (m = &cb->errno_map[0]; m->host_val; ++m)
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
666 cb_target_to_host_open (cb, target_val)
667      host_callback *cb;
668      int target_val;
669 {
670   int host_val = 0;
671   CB_TARGET_DEFS_MAP *m;
672
673   for (m = &cb->open_map[0]; m->host_val != -1; ++m)
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;
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
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 }
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.
733    The result is the size of the target's stat struct.  */
734
735 int
736 cb_host_to_target_stat (cb, hs, ts, big_p)
737      host_callback *cb;
738      const struct stat *hs;
739      PTR ts;
740      int big_p;
741 {
742   const char *m = cb->stat_map;
743   char *p = ts;
744
745   while (m)
746     {
747       char *q = strchr (m, ',');
748       int size;
749
750       /* FIXME: Use sscanf? */
751       if (q == NULL)
752         {
753           /* FIXME: print error message */
754           return;
755         }
756       size = atoi (q + 1);
757       if (size == 0)
758         {
759           /* FIXME: print error message */
760           return;
761         }
762
763       if (strncmp (m, "st_dev", q - m) == 0)
764         store (p, size, hs->st_dev, big_p);
765       else if (strncmp (m, "st_ino", q - m) == 0)
766         store (p, size, hs->st_ino, big_p);
767       /* FIXME:wip */
768       else
769         store (p, size, 0, big_p); /* unsupported field, store 0 */
770
771       p += size;
772       m = strchr (q, ':');
773       if (m)
774         ++m;
775     }
776 }
777 \f
778 /* Cover functions to the vfprintf callbacks.
779
780    ??? If one thinks of the callbacks as a subsystem onto itself [or part of
781    a larger "remote target subsystem"] with a well defined interface, then
782    one would think that the subsystem would provide these.  However, until
783    one is allowed to create such a subsystem (with its own source tree
784    independent of any particular user), such a critter can't exist.  Thus
785    these functions are here for the time being.  */
786
787 void
788 sim_cb_printf (host_callback *p, const char *fmt, ...)
789 {
790   va_list ap;
791
792   va_start (ap, fmt);
793   p->vprintf_filtered (p, fmt, ap);
794   va_end (ap);
795 }
796
797 void
798 sim_cb_eprintf (host_callback *p, const char *fmt, ...)
799 {
800   va_list ap;
801
802   va_start (ap, fmt);
803   p->evprintf_filtered (p, fmt, ap);
804   va_end (ap);
805 }