Add comment.
[external/binutils.git] / sim / common / callback.c
1 /* Host callback routines for GDB.
2    Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
3    Contributed by Cygnus Support.
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 this program; if not, write to the Free Software
19    Foundation, Inc., 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 #include <errno.h>
38 #include <fcntl.h>
39 #include <time.h>
40 #include "callback.h"
41 #include "targ-vals.h"
42
43 #ifdef HAVE_UNISTD_H
44 #include <unistd.h>
45 #endif
46
47 extern int system PARAMS ((const char *));
48
49 static int os_init PARAMS ((host_callback *));
50 static int os_shutdown PARAMS ((host_callback *));
51 static int os_unlink PARAMS ((host_callback *, const char *));
52 static long os_time PARAMS ((host_callback *, long *));
53 static int os_system PARAMS ((host_callback *, const char *));
54 static int os_rename PARAMS ((host_callback *, const char *, const char *));
55 static int os_write_stdout PARAMS ((host_callback *, const char *, int));
56 static void os_flush_stdout PARAMS ((host_callback *));
57 static int os_write_stderr PARAMS ((host_callback *, const char *, int));
58 static void os_flush_stderr PARAMS ((host_callback *));
59 static int os_write PARAMS ((host_callback *, int, const char *, int));
60 static int os_read_stdin PARAMS ((host_callback *, char *, int));
61 static int os_read PARAMS ((host_callback *, int, char *, int));
62 static int os_open PARAMS ((host_callback *, const char *, int));
63 static int os_lseek PARAMS ((host_callback *, int, long, int));
64 static int os_isatty PARAMS ((host_callback *, int));
65 static int os_get_errno PARAMS ((host_callback *));
66 static int os_close PARAMS ((host_callback *, int));
67 static void os_vprintf_filtered PARAMS ((host_callback *, const char *, va_list));
68 static void os_evprintf_filtered PARAMS ((host_callback *, const char *, va_list));
69 static void os_error PARAMS ((host_callback *, const char *, ...));
70 static int fdmap PARAMS ((host_callback *, int));
71 static int fdbad PARAMS ((host_callback *, int));
72 static int wrap PARAMS ((host_callback *, int));
73
74 /* Set the callback copy of errno from what we see now.  */
75
76 static int 
77 wrap (p, val)
78      host_callback *p;
79      int val;
80 {
81   p->last_errno = errno;
82   return val;
83 }
84
85 /* Make sure the FD provided is ok.  If not, return non-zero
86    and set errno. */
87
88 static int 
89 fdbad (p, fd)
90      host_callback *p;
91      int fd;
92 {
93   if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
94     {
95       p->last_errno = EINVAL;
96       return -1;
97     }
98   return 0;
99 }
100
101 static int 
102 fdmap (p, fd)
103      host_callback *p;
104      int fd;
105 {
106   return p->fdmap[fd];
107 }
108
109 static int 
110 os_close (p, fd)
111      host_callback *p;
112      int fd;
113 {
114   int result;
115
116   result = fdbad (p, fd);
117   if (result)
118     return result;
119   result = wrap (p, close (fdmap (p, fd)));
120   if(result == 0 && !p->alwaysopen[fd])
121     p->fdopen[fd] = 0;
122
123   return result;
124 }
125
126
127 /* taken from gdb/util.c - should be in a library */
128
129
130 #if defined(__GO32__) || defined (_WIN32)
131 static int
132 os_poll_quit (p)
133      host_callback *p;
134 {
135 #ifndef _MSC_VER
136   if (kbhit ())
137     {
138       int k = getkey ();
139       if (k == 1)
140         {
141           return 1;
142         }
143       else if (k == 2)
144         {
145           return 1;
146         }
147       else 
148         {
149           sim_cb_eprintf (p, "CTRL-A to quit, CTRL-B to quit harder\n");
150         }
151     }
152 #else /* !_MSC_VER */
153   /* NB - this will not compile! */
154   int k = win32pollquit();
155   if (k == 1)
156     return 1;
157   else if (k == 2)
158     return 1;
159 #endif /* !_MSC_VER */
160   return 0;
161 }
162 #else
163 #define os_poll_quit 0
164 #endif /* defined(__GO32__) || defined(_WIN32) */
165
166 static int 
167 os_get_errno (p)
168      host_callback *p;
169 {
170   return host_to_target_errno (p->last_errno);
171 }
172
173
174 static int 
175 os_isatty (p, fd)
176      host_callback *p;
177      int fd;
178 {
179   int result;
180
181   result = fdbad (p, fd);
182   if (result)
183     return result;
184   result = wrap (p, isatty (fdmap (p, fd)));
185
186   return result;
187 }
188
189 static int 
190 os_lseek (p, fd, off, way)
191      host_callback *p;
192      int fd;
193      long off;
194      int way;
195 {
196   int result;
197
198   result = fdbad (p, fd);
199   if (result)
200     return result;
201   result = lseek (fdmap (p, fd), off, way);
202   return result;
203 }
204
205 static int 
206 os_open (p, name, flags)
207      host_callback *p;
208      const char *name;
209      int flags;
210 {
211   int i;
212   for (i = 0; i < MAX_CALLBACK_FDS; i++)
213     {
214       if (!p->fdopen[i])
215         {
216           int f = open (name, target_to_host_open (flags), 0644);
217           if (f < 0)
218             {
219               p->last_errno = errno;
220               return f;
221             }
222           p->fdopen[i] = 1;
223           p->fdmap[i] = f;
224           return i;
225         }
226     }
227   p->last_errno = EMFILE;
228   return -1;
229 }
230
231 static int 
232 os_read (p, fd, buf, len)
233      host_callback *p;
234      int fd;
235      char *buf;
236      int len;
237 {
238   int result;
239
240   result = fdbad (p, fd);
241   if (result)
242     return result;
243   result = wrap (p, read (fdmap (p, fd), buf, len));
244   return result;
245 }
246
247 static int 
248 os_read_stdin (p, buf, len)
249      host_callback *p;
250      char *buf;
251      int len;
252 {
253   return wrap (p, read (0, buf, len));
254 }
255
256 static int 
257 os_write (p, fd, buf, len)
258      host_callback *p;
259      int fd;
260      const char *buf;
261      int len;
262 {
263   int result;
264
265   result = fdbad (p, fd);
266   if (result)
267     return result;
268   result = wrap (p, write (fdmap (p, fd), buf, len));
269   return result;
270 }
271
272 static int 
273 os_write_stdout (p, buf, len)
274      host_callback *p;
275      const char *buf;
276      int len;
277 {
278   return fwrite(buf, 1, len, stdout);
279 }
280
281 static void
282 os_flush_stdout (p)
283      host_callback *p;
284 {
285   fflush (stdout);
286 }
287
288 static int 
289 os_write_stderr (p, buf, len)
290      host_callback *p;
291      const char *buf;
292      int len;
293 {
294   return fwrite(buf, 1, len, stderr);
295 }
296
297 static void
298 os_flush_stderr (p)
299      host_callback *p;
300 {
301   fflush (stderr);
302 }
303
304 static int 
305 os_rename (p, f1, f2)
306      host_callback *p;
307      const char *f1;
308      const char *f2;
309 {
310   return wrap (p, rename (f1, f2));
311 }
312
313
314 static int
315 os_system (p, s)
316      host_callback *p;
317      const char *s;
318 {
319   return wrap (p, system (s));
320 }
321
322 static long 
323 os_time (p, t)
324      host_callback *p;
325      long *t;
326 {
327   return wrap (p, time (t));
328 }
329
330
331 static int 
332 os_unlink (p, f1)
333      host_callback *p;
334      const char *f1;
335 {
336   return wrap (p, unlink (f1));
337 }
338
339
340 static int
341 os_shutdown (p)
342      host_callback *p;
343 {
344   int i;
345   for (i = 0; i < MAX_CALLBACK_FDS; i++)
346     {
347       if (p->fdopen[i] && !p->alwaysopen[i]) {
348         close (p->fdmap[i]);
349         p->fdopen[i] = 0;
350       }
351     }
352   return 1;
353 }
354
355 static int
356 os_init(p)
357      host_callback *p;
358 {
359   int i;
360   os_shutdown (p);
361   for (i= 0; i < 3; i++)
362     {
363       p->fdmap[i] = i;
364       p->fdopen[i] = 1;
365       p->alwaysopen[i] = 1;
366     }
367   return 1;
368 }
369
370 /* DEPRECIATED */
371
372 /* VARARGS */
373 static void
374 #ifdef ANSI_PROTOTYPES
375 os_printf_filtered (host_callback *p, const char *format, ...)
376 #else
377 os_printf_filtered (p, va_alist)
378      host_callback *p;
379      va_dcl
380 #endif
381 {
382   va_list args;
383 #ifdef ANSI_PROTOTYPES
384   va_start (args, format);
385 #else
386   char *format;
387
388   va_start (args);
389   format = va_arg (args, char *);
390 #endif
391
392   vfprintf (stdout, format, args);
393   va_end (args);
394 }
395
396 /* VARARGS */
397 static void
398 #ifdef ANSI_PROTOTYPES
399 os_vprintf_filtered (host_callback *p, const char *format, va_list args)
400 #else
401 os_vprintf_filtered (p, format, args)
402      host_callback *p;
403      const char *format;
404      va_list args;
405 #endif
406 {
407   vprintf (format, args);
408 }
409
410 /* VARARGS */
411 static void
412 #ifdef ANSI_PROTOTYPES
413 os_evprintf_filtered (host_callback *p, const char *format, va_list args)
414 #else
415 os_evprintf_filtered (p, format, args)
416      host_callback *p;
417      const char *format;
418      va_list args;
419 #endif
420 {
421   vfprintf (stderr, format, args);
422 }
423
424 /* VARARGS */
425 static void
426 #ifdef ANSI_PROTOTYPES
427 os_error (host_callback *p, const char *format, ...)
428 #else
429 os_error (p, va_alist)
430      host_callback *p;
431      va_dcl
432 #endif
433 {
434   va_list args;
435 #ifdef ANSI_PROTOTYPES
436   va_start (args, format);
437 #else
438   char *format;
439
440   va_start (args);
441   format = va_arg (args, char *);
442 #endif
443
444   vfprintf (stderr, format, args);
445   fprintf (stderr, "\n");
446
447   va_end (args);
448   exit (1);
449 }
450
451 host_callback default_callback =
452 {
453   os_close,
454   os_get_errno,
455   os_isatty,
456   os_lseek,
457   os_open,
458   os_read,
459   os_read_stdin,
460   os_rename,
461   os_system,
462   os_time,
463   os_unlink,
464   os_write,
465   os_write_stdout,
466   os_flush_stdout,
467   os_write_stderr,
468   os_flush_stderr,
469
470   os_poll_quit,
471
472   os_shutdown,
473   os_init,
474
475   os_printf_filtered,  /* depreciated */
476
477   os_vprintf_filtered,
478   os_evprintf_filtered,
479   os_error,
480
481   0,            /* last errno */
482
483   { 0, },       /* fdmap */
484   { 0, },       /* fdopen */
485   { 0, },       /* alwaysopen */
486
487   HOST_CALLBACK_MAGIC,
488 };
489 \f
490 /* FIXME: Need to add hooks so target can tweak as necessary.  */
491
492 /* FIXME: struct stat conversion is missing.  */
493
494 /* FIXME: sort tables if large.
495    Alternatively, an obvious improvement for errno conversion is
496    to machine generate a function with a large switch().  */
497
498 int
499 host_to_target_errno (host_val)
500      int host_val;
501 {
502   target_defs_map *m;
503
504   for (m = &errno_map[0]; m->host_val; ++m)
505     if (m->host_val == host_val)
506       return m->target_val;
507
508   /* ??? Which error to return in this case is up for grabs.
509      Note that some missing values may have standard alternatives.
510      For now return 0 and require caller to deal with it.  */
511   return 0;
512 }
513
514 /* Given a set of target bitmasks for the open system call,
515    return the host equivalent.
516    Mapping open flag values is best done by looping so there's no need
517    to machine generate this function.  */
518
519 int
520 target_to_host_open (target_val)
521      int target_val;
522 {
523   int host_val = 0;
524   target_defs_map *m;
525
526   for (m = &open_map[0]; m->host_val != -1; ++m)
527     {
528       switch (m->target_val)
529         {
530           /* O_RDONLY can be (and usually is) 0 which needs to be treated
531              specially.  */
532         case TARGET_O_RDONLY :
533         case TARGET_O_WRONLY :
534         case TARGET_O_RDWR :
535           if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
536               == m->target_val)
537             host_val |= m->host_val;
538           /* Handle the host/target differentiating between binary and
539              text mode.  Only one case is of importance */
540 #if ! defined (TARGET_O_BINARY) && defined (O_BINARY)
541           host_val |= O_BINARY;
542 #endif
543           break;
544         default :
545           if ((m->target_val & target_val) == m->target_val)
546             host_val |= m->host_val;
547           break;
548         }
549     }
550
551   return host_val;
552 }
553 \f
554 /* Cover functions to the vfprintf callbacks.
555
556    ??? If one thinks of the callbacks as a subsystem onto itself [or part of
557    a larger "remote target subsystem"] with a well defined interface, then
558    one would think that the subsystem would provide these.  However, until
559    one is allowed to create such a subsystem (with its own source tree
560    independent of any particular user), such a critter can't exist.  Thus
561    these functions are here for the time being.  */
562
563 void
564 sim_cb_printf (host_callback *p, const char *fmt, ...)
565 {
566   va_list ap;
567
568   va_start (ap, fmt);
569   p->vprintf_filtered (p, fmt, ap);
570   va_end (ap);
571 }
572
573 void
574 sim_cb_eprintf (host_callback *p, const char *fmt, ...)
575 {
576   va_list ap;
577
578   va_start (ap, fmt);
579   p->evprintf_filtered (p, fmt, ap);
580   va_end (ap);
581 }