* callback.c (os_close): Mark the descriptor as being
[external/binutils.git] / sim / common / callback.c
1 /* Host callback routines for GDB.
2    Copyright 1995, 1996 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 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           p->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 {
210   int i;
211   for (i = 0; i < MAX_CALLBACK_FDS; i++)
212     {
213       if (!p->fdopen[i])
214         {
215           int f = open (name, target_to_host_open (flags), 0644);
216           if (f < 0)
217             {
218               p->last_errno = errno;
219               return f;
220             }
221           p->fdopen[i] = 1;
222           p->fdmap[i] = f;
223           return i;
224         }
225     }
226   p->last_errno = EMFILE;
227   return -1;
228 }
229
230 static int 
231 os_read (p, fd, buf, len)
232      host_callback *p;
233      int fd;
234      char *buf;
235      int len;
236 {
237   int result;
238
239   result = fdbad (p, fd);
240   if (result)
241     return result;
242   result = wrap (p, read (fdmap (p, fd), buf, len));
243   return result;
244 }
245
246 static int 
247 os_read_stdin (p, buf, len)
248      host_callback *p;
249      char *buf;
250      int len;
251 {
252   return wrap (p, read (0, buf, len));
253 }
254
255 static int 
256 os_write (p, fd, buf, len)
257      host_callback *p;
258      int fd;
259      const char *buf;
260      int len;
261 {
262   int result;
263
264   result = fdbad (p, fd);
265   if (result)
266     return result;
267   result = wrap (p, write (fdmap (p, fd), buf, len));
268   return result;
269 }
270
271 static int 
272 os_write_stdout (p, buf, len)
273      host_callback *p;
274      const char *buf;
275      int len;
276 {
277   return fwrite(buf, 1, len, stdout);
278 }
279
280 static void
281 os_flush_stdout (p)
282      host_callback *p;
283 {
284   fflush (stdout);
285 }
286
287 static int 
288 os_write_stderr (p, buf, len)
289      host_callback *p;
290      const char *buf;
291      int len;
292 {
293   return fwrite(buf, 1, len, stderr);
294 }
295
296 static void
297 os_flush_stderr (p)
298      host_callback *p;
299 {
300   fflush (stderr);
301 }
302
303 static int 
304 os_rename (p, f1, f2)
305      host_callback *p;
306      const char *f1;
307      const char *f2;
308 {
309   return wrap (p, rename (f1, f2));
310 }
311
312
313 static int
314 os_system (p, s)
315      host_callback *p;
316      const char *s;
317 {
318   return wrap (p, system (s));
319 }
320
321 static long 
322 os_time (p, t)
323      host_callback *p;
324      long *t;
325 {
326   return wrap (p, time (t));
327 }
328
329
330 static int 
331 os_unlink (p, f1)
332      host_callback *p;
333      const char *f1;
334 {
335   return wrap (p, unlink (f1));
336 }
337
338
339 static int
340 os_shutdown (p)
341      host_callback *p;
342 {
343   int i;
344   for (i = 0; i < MAX_CALLBACK_FDS; i++)
345     {
346       if (p->fdopen[i] && !p->alwaysopen[i]) {
347         close (p->fdmap[i]);
348         p->fdopen[i] = 0;
349       }
350     }
351   return 1;
352 }
353
354 static int
355 os_init(p)
356      host_callback *p;
357 {
358   int i;
359   os_shutdown (p);
360   for (i= 0; i < 3; i++)
361     {
362       p->fdmap[i] = i;
363       p->fdopen[i] = 1;
364       p->alwaysopen[i] = 1;
365     }
366   return 1;
367 }
368
369 /* DEPRECIATED */
370
371 /* VARARGS */
372 static void
373 #ifdef ANSI_PROTOTYPES
374 os_printf_filtered (host_callback *p, const char *format, ...)
375 #else
376 os_printf_filtered (p, va_alist)
377      host_callback *p;
378      va_dcl
379 #endif
380 {
381   va_list args;
382 #ifdef ANSI_PROTOTYPES
383   va_start (args, format);
384 #else
385   char *format;
386
387   va_start (args);
388   format = va_arg (args, char *);
389 #endif
390
391   vfprintf (stdout, format, args);
392   va_end (args);
393 }
394
395 /* VARARGS */
396 static void
397 #ifdef ANSI_PROTOTYPES
398 os_vprintf_filtered (host_callback *p, const char *format, va_list args)
399 #else
400 os_vprintf_filtered (p, format, args)
401      host_callback *p;
402      const char *format;
403      va_list args;
404 #endif
405 {
406   vprintf (format, args);
407 }
408
409 /* VARARGS */
410 static void
411 #ifdef ANSI_PROTOTYPES
412 os_evprintf_filtered (host_callback *p, const char *format, va_list args)
413 #else
414 os_evprintf_filtered (p, format, args)
415      host_callback *p;
416      const char *format;
417      va_list args;
418 #endif
419 {
420   vfprintf (stderr, format, args);
421 }
422
423 /* VARARGS */
424 static void
425 #ifdef ANSI_PROTOTYPES
426 os_error (host_callback *p, const char *format, ...)
427 #else
428 os_error (p, va_alist)
429      host_callback *p;
430      va_dcl
431 #endif
432 {
433   va_list args;
434 #ifdef ANSI_PROTOTYPES
435   va_start (args, format);
436 #else
437   char *format;
438
439   va_start (args);
440   format = va_arg (args, char *);
441 #endif
442
443   vfprintf (stderr, format, args);
444   fprintf (stderr, "\n");
445
446   va_end (args);
447   exit (1);
448 }
449
450 host_callback default_callback =
451 {
452   os_close,
453   os_get_errno,
454   os_isatty,
455   os_lseek,
456   os_open,
457   os_read,
458   os_read_stdin,
459   os_rename,
460   os_system,
461   os_time,
462   os_unlink,
463   os_write,
464   os_write_stdout,
465   os_flush_stdout,
466   os_write_stderr,
467   os_flush_stderr,
468
469   os_poll_quit,
470
471   os_shutdown,
472   os_init,
473
474   os_printf_filtered,  /* depreciated */
475
476   os_vprintf_filtered,
477   os_evprintf_filtered,
478   os_error,
479
480   0,            /* last errno */
481
482   { 0, },       /* fdmap */
483   { 0, },       /* fdopen */
484   { 0, },       /* alwaysopen */
485
486   HOST_CALLBACK_MAGIC,
487 };
488 \f
489 /* FIXME: Need to add hooks so target can tweak as necessary.  */
490
491 /* FIXME: struct stat conversion is missing.  */
492
493 /* FIXME: sort tables if large.
494    Alternatively, an obvious improvement for errno conversion is
495    to machine generate a function with a large switch().  */
496
497 int
498 host_to_target_errno (host_val)
499      int host_val;
500 {
501   target_defs_map *m;
502
503   for (m = &errno_map[0]; m->host_val; ++m)
504     if (m->host_val == host_val)
505       return m->target_val;
506
507   /* ??? Which error to return in this case is up for grabs.
508      Note that some missing values may have standard alternatives.
509      For now return 0 and require caller to deal with it.  */
510   return 0;
511 }
512
513 /* Given a set of target bitmasks for the open system call,
514    return the host equivalent.
515    Mapping open flag values is best done by looping so there's no need
516    to machine generate this function.  */
517
518 int
519 target_to_host_open (target_val)
520      int target_val;
521 {
522   int host_val = 0;
523   target_defs_map *m;
524
525   for (m = &open_map[0]; m->host_val != -1; ++m)
526     {
527       switch (m->target_val)
528         {
529           /* O_RDONLY can be (and usually is) 0 which needs to be treated
530              specially.  */
531         case TARGET_O_RDONLY :
532         case TARGET_O_WRONLY :
533         case TARGET_O_RDWR :
534           if ((target_val & (TARGET_O_RDONLY | TARGET_O_WRONLY | TARGET_O_RDWR))
535               == m->target_val)
536             host_val |= m->host_val;
537           break;
538         default :
539           if ((m->target_val & target_val) == m->target_val)
540             host_val |= m->host_val;
541           break;
542         }
543     }
544
545   return host_val;
546 }