import gdb-1999-10-11 snapshot
[external/binutils.git] / gdb / serial.c
1 /* Generic serial interface routines
2    Copyright 1992, 1993, 1996, 1997, 1999 Free Software Foundation, Inc.
3
4    This file is part of GDB.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20
21 #include "defs.h"
22 #include <ctype.h>
23 #include "serial.h"
24 #include "gdb_string.h"
25 #include "gdbcmd.h"
26
27 extern void _initialize_serial (void);
28
29 /* Is serial being debugged? */
30
31 static int global_serial_debug_p;
32
33 /* Linked list of serial I/O handlers */
34
35 static struct serial_ops *serial_ops_list = NULL;
36
37 /* This is the last serial stream opened.  Used by connect command. */
38
39 static serial_t last_serial_opened = NULL;
40
41 /* Pointer to list of scb's. */
42
43 static serial_t scb_base;
44
45 /* Non-NULL gives filename which contains a recording of the remote session,
46    suitable for playback by gdbserver. */
47
48 static char *serial_logfile = NULL;
49 static GDB_FILE *serial_logfp = NULL;
50
51 static struct serial_ops *serial_interface_lookup (char *);
52 static void serial_logchar (struct gdb_file *stream, int ch_type, int ch, int timeout);
53 static char logbase_hex[] = "hex";
54 static char logbase_octal[] = "octal";
55 static char logbase_ascii[] = "ascii";
56 static char *logbase_enums[] =
57 {logbase_hex, logbase_octal, logbase_ascii, NULL};
58 static char *serial_logbase = logbase_ascii;
59 \f
60
61
62 static int serial_current_type = 0;
63
64 /* Log char CH of type CHTYPE, with TIMEOUT */
65
66 /* Define bogus char to represent a BREAK.  Should be careful to choose a value
67    that can't be confused with a normal char, or an error code.  */
68 #define SERIAL_BREAK 1235
69
70 static void
71 serial_logchar (struct gdb_file *stream, int ch_type, int ch, int timeout)
72 {
73   if (ch_type != serial_current_type)
74     {
75       fprintf_unfiltered (stream, "\n%c ", ch_type);
76       serial_current_type = ch_type;
77     }
78
79   if (serial_logbase != logbase_ascii)
80     fputc_unfiltered (' ', stream);
81
82   switch (ch)
83     {
84     case SERIAL_TIMEOUT:
85       fprintf_unfiltered (stream, "<Timeout: %d seconds>", timeout);
86       return;
87     case SERIAL_ERROR:
88       fprintf_unfiltered (stream, "<Error: %s>", safe_strerror (errno));
89       return;
90     case SERIAL_EOF:
91       fputs_unfiltered ("<Eof>", stream);
92       return;
93     case SERIAL_BREAK:
94       fputs_unfiltered ("<Break>", stream);
95       return;
96     default:
97       if (serial_logbase == logbase_hex)
98         fprintf_unfiltered (stream, "%02x", ch & 0xff);
99       else if (serial_logbase == logbase_octal)
100         fprintf_unfiltered (stream, "%03o", ch & 0xff);
101       else
102         switch (ch)
103           {
104           case '\\':
105             fputs_unfiltered ("\\\\", stream);
106             break;
107           case '\b':
108             fputs_unfiltered ("\\b", stream);
109             break;
110           case '\f':
111             fputs_unfiltered ("\\f", stream);
112             break;
113           case '\n':
114             fputs_unfiltered ("\\n", stream);
115             break;
116           case '\r':
117             fputs_unfiltered ("\\r", stream);
118             break;
119           case '\t':
120             fputs_unfiltered ("\\t", stream);
121             break;
122           case '\v':
123             fputs_unfiltered ("\\v", stream);
124             break;
125           default:
126             fprintf_unfiltered (stream, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF);
127             break;
128           }
129     }
130 }
131
132 void
133 serial_log_command (const char *cmd)
134 {
135   if (!serial_logfp)
136     return;
137
138   serial_current_type = 'c';
139
140   fputs_unfiltered ("\nc ", serial_logfp);
141   fputs_unfiltered (cmd, serial_logfp);
142
143   /* Make sure that the log file is as up-to-date as possible,
144      in case we are getting ready to dump core or something. */
145   gdb_flush (serial_logfp);
146 }
147
148 \f
149 static struct serial_ops *
150 serial_interface_lookup (char *name)
151 {
152   struct serial_ops *ops;
153
154   for (ops = serial_ops_list; ops; ops = ops->next)
155     if (strcmp (name, ops->name) == 0)
156       return ops;
157
158   return NULL;
159 }
160
161 void
162 serial_add_interface (struct serial_ops *optable)
163 {
164   optable->next = serial_ops_list;
165   serial_ops_list = optable;
166 }
167
168 /* Open up a device or a network socket, depending upon the syntax of NAME. */
169
170 serial_t
171 serial_open (const char *name)
172 {
173   serial_t scb;
174   struct serial_ops *ops;
175   const char *open_name = name;
176
177   for (scb = scb_base; scb; scb = scb->next)
178     if (scb->name && strcmp (scb->name, name) == 0)
179       {
180         scb->refcnt++;
181         return scb;
182       }
183
184   if (strcmp (name, "ocd") == 0)
185     ops = serial_interface_lookup ("ocd");
186   else if (strcmp (name, "pc") == 0)
187     ops = serial_interface_lookup ("pc");
188   else if (strchr (name, ':'))
189     ops = serial_interface_lookup ("tcp");
190   else if (strncmp (name, "lpt", 3) == 0)
191     ops = serial_interface_lookup ("parallel");
192   else if (strncmp (name, "|", 1) == 0)
193     {
194       ops = serial_interface_lookup ("pipe");
195       open_name = name + 1; /* discard ``|'' */
196     }
197   else
198     ops = serial_interface_lookup ("hardwire");
199
200   if (!ops)
201     return NULL;
202
203   scb = (serial_t) xmalloc (sizeof (struct _serial_t));
204
205   scb->ops = ops;
206
207   scb->bufcnt = 0;
208   scb->bufp = scb->buf;
209
210   if (scb->ops->open (scb, open_name))
211     {
212       free (scb);
213       return NULL;
214     }
215
216   scb->name = strsave (name);
217   scb->next = scb_base;
218   scb->refcnt = 1;
219   scb->debug_p = 0;
220   scb->async_state = 0;
221   scb->async_handler = NULL;
222   scb->async_context = NULL;
223   scb_base = scb;
224
225   last_serial_opened = scb;
226
227   if (serial_logfile != NULL)
228     {
229       serial_logfp = gdb_fopen (serial_logfile, "w");
230       if (serial_logfp == NULL)
231         perror_with_name (serial_logfile);
232     }
233
234   return scb;
235 }
236
237 serial_t
238 serial_fdopen (const int fd)
239 {
240   serial_t scb;
241   struct serial_ops *ops;
242
243   for (scb = scb_base; scb; scb = scb->next)
244     if (scb->fd == fd)
245       {
246         scb->refcnt++;
247         return scb;
248       }
249
250   ops = serial_interface_lookup ("hardwire");
251
252   if (!ops)
253     return NULL;
254
255   scb = (serial_t) xmalloc (sizeof (struct _serial_t));
256
257   scb->ops = ops;
258
259   scb->bufcnt = 0;
260   scb->bufp = scb->buf;
261
262   scb->fd = fd;
263
264   scb->name = NULL;
265   scb->next = scb_base;
266   scb->refcnt = 1;
267   scb->debug_p = 0;
268   scb->async_state = 0;
269   scb->async_handler = NULL;
270   scb->async_context = NULL;
271   scb_base = scb;
272
273   last_serial_opened = scb;
274
275   return scb;
276 }
277
278 static void
279 do_serial_close (serial_t scb, int really_close)
280 {
281   serial_t tmp_scb;
282
283   last_serial_opened = NULL;
284
285   if (serial_logfp)
286     {
287       fputs_unfiltered ("\nEnd of log\n", serial_logfp);
288       serial_current_type = 0;
289
290       /* XXX - What if serial_logfp == gdb_stdout or gdb_stderr? */
291       gdb_fclose (&serial_logfp);
292       serial_logfp = NULL;
293     }
294
295 /* This is bogus.  It's not our fault if you pass us a bad scb...!  Rob, you
296    should fix your code instead.  */
297
298   if (!scb)
299     return;
300
301   scb->refcnt--;
302   if (scb->refcnt > 0)
303     return;
304
305   /* ensure that the FD has been taken out of async mode */
306   if (scb->async_handler != NULL)
307     serial_async (scb, NULL, NULL);
308
309   if (really_close)
310     scb->ops->close (scb);
311
312   if (scb->name)
313     free (scb->name);
314
315   if (scb_base == scb)
316     scb_base = scb_base->next;
317   else
318     for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
319       {
320         if (tmp_scb->next != scb)
321           continue;
322
323         tmp_scb->next = tmp_scb->next->next;
324         break;
325       }
326
327   free (scb);
328 }
329
330 void
331 serial_close (serial_t scb)
332 {
333   do_serial_close (scb, 1);
334 }
335
336 void
337 serial_un_fdopen (serial_t scb)
338 {
339   do_serial_close (scb, 0);
340 }
341
342 int
343 serial_readchar (serial_t scb, int timeout)
344 {
345   int ch;
346
347   /* FIXME: cagney/1999-10-11: Don't enable this check until the ASYNC
348      code is finished. */
349   if (0 && SERIAL_IS_ASYNC_P (scb) && timeout < 0)
350     internal_error ("serial_readchar: blocking read in async mode");
351
352   ch = scb->ops->readchar (scb, timeout);
353   if (serial_logfp != NULL)
354     {
355       serial_logchar (serial_logfp, 'r', ch, timeout);
356
357       /* Make sure that the log file is as up-to-date as possible,
358          in case we are getting ready to dump core or something. */
359       gdb_flush (serial_logfp);
360     }
361   if (SERIAL_DEBUG_P (scb))
362     {
363       fprintf_unfiltered (gdb_stdlog, "[");
364       serial_logchar (gdb_stdlog, 'r', ch, timeout);
365       fprintf_unfiltered (gdb_stdlog, "]");
366       gdb_flush (gdb_stdlog);
367     }
368
369   return (ch);
370 }
371
372 int
373 serial_write (serial_t scb, const char *str, int len)
374 {
375   if (serial_logfp != NULL)
376     {
377       int count;
378
379       for (count = 0; count < len; count++)
380         serial_logchar (serial_logfp, 'w', str[count] & 0xff, 0);
381
382       /* Make sure that the log file is as up-to-date as possible,
383          in case we are getting ready to dump core or something. */
384       gdb_flush (serial_logfp);
385     }
386
387   return (scb->ops->write (scb, str, len));
388 }
389
390 void
391 serial_printf (serial_t desc, const char *format,...)
392 {
393   va_list args;
394   char *buf;
395   va_start (args, format);
396
397   vasprintf (&buf, format, args);
398   SERIAL_WRITE (desc, buf, strlen (buf));
399
400   free (buf);
401   va_end (args);
402 }
403
404 int
405 serial_drain_output (serial_t scb)
406 {
407   return scb->ops->drain_output (scb);
408 }
409
410 int
411 serial_flush_output (serial_t scb)
412 {
413   return scb->ops->flush_output (scb);
414 }
415
416 int
417 serial_flush_input (serial_t scb)
418 {
419   return scb->ops->flush_input (scb);
420 }
421
422 int
423 serial_send_break (serial_t scb)
424 {
425   if (serial_logfp != NULL)
426     serial_logchar (serial_logfp, 'w', SERIAL_BREAK, 0);
427
428   return (scb->ops->send_break (scb));
429 }
430
431 void
432 serial_raw (serial_t scb)
433 {
434   scb->ops->go_raw (scb);
435 }
436
437 serial_ttystate
438 serial_get_tty_state (serial_t scb)
439 {
440   return scb->ops->get_tty_state (scb);
441 }
442
443 int
444 serial_set_tty_state (serial_t scb, serial_ttystate ttystate)
445 {
446   return scb->ops->set_tty_state (scb, ttystate);
447 }
448
449 void
450 serial_print_tty_state (serial_t scb,
451                         serial_ttystate ttystate,
452                         struct gdb_file *stream)
453 {
454   scb->ops->print_tty_state (scb, ttystate, stream);
455 }
456
457 int
458 serial_noflush_set_tty_state (serial_t scb,
459                               serial_ttystate new_ttystate,
460                               serial_ttystate old_ttystate)
461 {
462   return scb->ops->noflush_set_tty_state (scb, new_ttystate, old_ttystate);
463 }
464
465 int
466 serial_setbaudrate (serial_t scb, int rate)
467 {
468   return scb->ops->setbaudrate (scb, rate);
469 }
470
471 int
472 serial_setstopbits (serial_t scb, int num)
473 {
474   return scb->ops->setstopbits (scb, num);
475 }
476
477 int
478 serial_can_async_p (serial_t scb)
479 {
480   return (scb->ops->async != NULL);
481 }
482
483 int
484 serial_is_async_p (serial_t scb)
485 {
486   return (scb->ops->async != NULL) && (scb->async_handler != NULL);
487 }
488
489 void
490 serial_async (serial_t scb,
491               serial_event_ftype *handler,
492               void *context)
493 {
494   /* Only change mode if there is a need. */
495   if ((scb->async_handler == NULL)
496       != (handler == NULL))
497     scb->ops->async (scb, handler != NULL);
498   scb->async_handler = handler;
499   scb->async_context = context;
500 }
501
502 int
503 deprecated_serial_fd (serial_t scb)
504 {
505   /* FIXME: should this output a warning that deprecated code is being
506      called? */
507   if (scb->fd < 0)
508     {
509       internal_error ("serial: FD not valid");
510     }
511   return scb->fd; /* sigh */
512 }
513
514 void
515 serial_debug (serial_t scb, int debug_p)
516 {
517   scb->debug_p = debug_p;
518 }
519
520 int
521 serial_debug_p (serial_t scb)
522 {
523   return scb->debug_p || global_serial_debug_p;
524 }
525
526
527 #if 0
528 /*
529    The connect command is #if 0 because I hadn't thought of an elegant
530    way to wait for I/O on two serial_t's simultaneously.  Two solutions
531    came to mind:
532
533    1) Fork, and have have one fork handle the to user direction,
534    and have the other hand the to target direction.  This
535    obviously won't cut it for MSDOS.
536
537    2) Use something like select.  This assumes that stdin and
538    the target side can both be waited on via the same
539    mechanism.  This may not be true for DOS, if GDB is
540    talking to the target via a TCP socket.
541    -grossman, 8 Jun 93
542  */
543
544 /* Connect the user directly to the remote system.  This command acts just like
545    the 'cu' or 'tip' command.  Use <CR>~. or <CR>~^D to break out.  */
546
547 static serial_t tty_desc;       /* Controlling terminal */
548
549 static void
550 cleanup_tty (serial_ttystate ttystate)
551 {
552   printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
553   SERIAL_SET_TTY_STATE (tty_desc, ttystate);
554   free (ttystate);
555   SERIAL_CLOSE (tty_desc);
556 }
557
558 static void
559 connect_command (char *args, int fromtty)
560 {
561   int c;
562   char cur_esc = 0;
563   serial_ttystate ttystate;
564   serial_t port_desc;           /* TTY port */
565
566   dont_repeat ();
567
568   if (args)
569     fprintf_unfiltered (gdb_stderr, "This command takes no args.  They have been ignored.\n");
570
571   printf_unfiltered ("[Entering connect mode.  Use ~. or ~^D to escape]\n");
572
573   tty_desc = SERIAL_FDOPEN (0);
574   port_desc = last_serial_opened;
575
576   ttystate = SERIAL_GET_TTY_STATE (tty_desc);
577
578   SERIAL_RAW (tty_desc);
579   SERIAL_RAW (port_desc);
580
581   make_cleanup (cleanup_tty, ttystate);
582
583   while (1)
584     {
585       int mask;
586
587       mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
588
589       if (mask & 2)
590         {                       /* tty input */
591           char cx;
592
593           while (1)
594             {
595               c = SERIAL_READCHAR (tty_desc, 0);
596
597               if (c == SERIAL_TIMEOUT)
598                 break;
599
600               if (c < 0)
601                 perror_with_name ("connect");
602
603               cx = c;
604               SERIAL_WRITE (port_desc, &cx, 1);
605
606               switch (cur_esc)
607                 {
608                 case 0:
609                   if (c == '\r')
610                     cur_esc = c;
611                   break;
612                 case '\r':
613                   if (c == '~')
614                     cur_esc = c;
615                   else
616                     cur_esc = 0;
617                   break;
618                 case '~':
619                   if (c == '.' || c == '\004')
620                     return;
621                   else
622                     cur_esc = 0;
623                 }
624             }
625         }
626
627       if (mask & 1)
628         {                       /* Port input */
629           char cx;
630
631           while (1)
632             {
633               c = SERIAL_READCHAR (port_desc, 0);
634
635               if (c == SERIAL_TIMEOUT)
636                 break;
637
638               if (c < 0)
639                 perror_with_name ("connect");
640
641               cx = c;
642
643               SERIAL_WRITE (tty_desc, &cx, 1);
644             }
645         }
646     }
647 }
648 #endif /* 0 */
649
650 void
651 _initialize_serial (void)
652 {
653 #if 0
654   add_com ("connect", class_obscure, connect_command,
655            "Connect the terminal directly up to the command monitor.\n\
656 Use <CR>~. or <CR>~^D to break out.");
657 #endif /* 0 */
658
659   add_show_from_set
660     (add_set_cmd ("remotelogfile", no_class,
661                   var_filename, (char *) &serial_logfile,
662                   "Set filename for remote session recording.\n\
663 This file is used to record the remote session for future playback\n\
664 by gdbserver.",
665                   &setlist),
666      &showlist);
667
668   add_show_from_set
669     (add_set_enum_cmd ("remotelogbase", no_class,
670                        logbase_enums, (char *) &serial_logbase,
671                        "Set numerical base for remote session logging",
672                        &setlist),
673      &showlist);
674
675   add_show_from_set (add_set_cmd ("serialdebug",
676                                   class_maintenance,
677                                   var_zinteger,
678                                   (char *)&global_serial_debug_p,
679                                   "Set serial debugging.\n\
680 When non-zero, serial port debugging is enabled.", &setlist),
681                      &showlist);
682 }