* remote-mips.c: Use the correct name everywhere (DDB) for NEC's
[deliverable/binutils-gdb.git] / gdb / serial.c
CommitLineData
4e772f44 1/* Generic serial interface routines
c84e5000 2 Copyright 1992, 1993, 1996 Free Software Foundation, Inc.
4e772f44
SG
3
4This file is part of GDB.
5
6This program is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2 of the License, or
9(at your option) any later version.
10
11This program is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with this program; if not, write to the Free Software
6c9638b4 18Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
4e772f44
SG
19
20#include "defs.h"
72ae15f6 21#include <ctype.h>
4e772f44 22#include "serial.h"
0694bce6 23#include "gdb_string.h"
e8f1ad9a 24#include "gdbcmd.h"
4e772f44 25
38dc5e12 26/* Linked list of serial I/O handlers */
4e772f44
SG
27
28static struct serial_ops *serial_ops_list = NULL;
29
38dc5e12
SG
30/* This is the last serial stream opened. Used by connect command. */
31
32static serial_t last_serial_opened = NULL;
33
bbcc95bd
PS
34/* Pointer to list of scb's. */
35
36static serial_t scb_base;
37
e8f1ad9a
FF
38/* Non-NULL gives filename which contains a recording of the remote session,
39 suitable for playback by gdbserver. */
40
d9951af4
SG
41static char *serial_logfile = NULL;
42static FILE *serial_logfp = NULL;
e8f1ad9a 43
b607efe7 44static struct serial_ops *serial_interface_lookup PARAMS ((char *));
d9951af4
SG
45static void serial_logchar PARAMS ((int ch, int timeout));
46static char logbase_hex[] = "hex";
47static char logbase_octal[] = "octal";
48static char logbase_ascii[] = "ascii";
49static char *logbase_enums[] = {logbase_hex, logbase_octal, logbase_ascii, NULL};
50static char *serial_logbase = logbase_ascii;
b607efe7 51
e8f1ad9a
FF
52\f
53static int serial_reading = 0;
54static int serial_writing = 0;
55
56void
57serial_log_command (cmd)
58 const char *cmd;
59{
d9951af4
SG
60 if (!serial_logfp)
61 return;
62
e8f1ad9a
FF
63 if (serial_reading || serial_writing)
64 {
0db5a6fe 65 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
66 serial_reading = 0;
67 serial_writing = 0;
68 }
0db5a6fe 69 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
e8f1ad9a
FF
70 /* Make sure that the log file is as up-to-date as possible,
71 in case we are getting ready to dump core or something. */
72 fflush (serial_logfp);
73}
74
d9951af4
SG
75/* Define bogus char to represent a BREAK. Should be careful to choose a value
76 that can't be confused with a normal char, or an error code. */
77#define SERIAL_BREAK 1235
78
e8f1ad9a 79static void
d9951af4 80serial_logchar (ch, timeout)
e8f1ad9a 81 int ch;
d9951af4 82 int timeout;
e8f1ad9a 83{
d9951af4
SG
84 if (serial_logbase != logbase_ascii)
85 fputc_unfiltered (' ', serial_logfp);
86
e8f1ad9a
FF
87 switch (ch)
88 {
d9951af4
SG
89 case SERIAL_TIMEOUT:
90 fprintf_unfiltered (serial_logfp, "<Timeout: %d seconds>", timeout);
91 return;
92 case SERIAL_ERROR:
93 fprintf_unfiltered (serial_logfp, "<Error: %s>", safe_strerror (errno));
94 return;
95 case SERIAL_EOF:
96 fputs_unfiltered ("<Eof>", serial_logfp);
97 return;
98 case SERIAL_BREAK:
99 fputs_unfiltered ("<Break>", serial_logfp);
100 return;
101 default:
102 if (serial_logbase == logbase_hex)
103 fprintf_unfiltered (serial_logfp, "%02x", ch & 0xff);
104 else if (serial_logbase == logbase_octal)
105 fprintf_unfiltered (serial_logfp, "%03o", ch & 0xff);
106 else
107 switch (ch)
108 {
109 case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
110 case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
111 case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
112 case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
113 case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
114 case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
115 case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
116 default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
117 }
118 }
e8f1ad9a
FF
119}
120
121int
122serial_write (scb, str, len)
123 serial_t scb;
124 const char *str;
125 int len;
126{
127 int count;
128
129 if (serial_logfp != NULL)
130 {
131 if (serial_reading)
132 {
0db5a6fe 133 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
134 serial_reading = 0;
135 }
136 if (!serial_writing)
137 {
d9951af4 138 fputs_unfiltered ("w ", serial_logfp);
e8f1ad9a
FF
139 serial_writing = 1;
140 }
141 for (count = 0; count < len; count++)
142 {
d9951af4 143 serial_logchar (str[count] & 0xff, 0);
e8f1ad9a
FF
144 }
145 /* Make sure that the log file is as up-to-date as possible,
146 in case we are getting ready to dump core or something. */
147 fflush (serial_logfp);
148 }
149 return (scb -> ops -> write (scb, str, len));
150}
151
152int
153serial_readchar (scb, timeout)
154 serial_t scb;
155 int timeout;
156{
157 int ch;
158
159 ch = scb -> ops -> readchar (scb, timeout);
160 if (serial_logfp != NULL)
161 {
162 if (serial_writing)
163 {
0db5a6fe 164 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
165 serial_writing = 0;
166 }
167 if (!serial_reading)
168 {
d9951af4 169 fputs_unfiltered ("r ", serial_logfp);
e8f1ad9a
FF
170 serial_reading = 1;
171 }
d9951af4 172 serial_logchar (ch, timeout);
e8f1ad9a
FF
173 /* Make sure that the log file is as up-to-date as possible,
174 in case we are getting ready to dump core or something. */
175 fflush (serial_logfp);
176 }
177 return (ch);
178}
179
d9951af4
SG
180int
181serial_send_break (scb)
182 serial_t scb;
183{
184 if (serial_logfp != NULL)
185 {
186 if (serial_reading)
187 {
188 fputc_unfiltered ('\n', serial_logfp);
189 serial_reading = 0;
190 }
191 if (!serial_writing)
192 {
193 fputs_unfiltered ("w ", serial_logfp);
194 serial_writing = 1;
195 }
196 serial_logchar (SERIAL_BREAK, 0);
197 /* Make sure that the log file is as up-to-date as possible,
198 in case we are getting ready to dump core or something. */
199 fflush (serial_logfp);
200 }
201 return (scb -> ops -> send_break (scb));
202}
203
4e772f44
SG
204static struct serial_ops *
205serial_interface_lookup (name)
206 char *name;
207{
208 struct serial_ops *ops;
209
210 for (ops = serial_ops_list; ops; ops = ops->next)
211 if (strcmp (name, ops->name) == 0)
212 return ops;
213
214 return NULL;
215}
216
217void
218serial_add_interface(optable)
219 struct serial_ops *optable;
220{
221 optable->next = serial_ops_list;
222 serial_ops_list = optable;
223}
224
38dc5e12
SG
225/* Open up a device or a network socket, depending upon the syntax of NAME. */
226
4e772f44 227serial_t
55679787 228serial_open (name)
4e772f44
SG
229 const char *name;
230{
231 serial_t scb;
232 struct serial_ops *ops;
233
4887063b
SG
234 for (scb = scb_base; scb; scb = scb->next)
235 if (scb->name && strcmp (scb->name, name) == 0)
236 {
237 scb->refcnt++;
238 return scb;
239 }
240
55679787
SC
241 if (strcmp (name, "pc") == 0)
242 ops = serial_interface_lookup ("pc");
243 else if (strchr (name, ':'))
38dc5e12 244 ops = serial_interface_lookup ("tcp");
c84e5000
SC
245 else if (strncmp (name, "lpt", 3) == 0)
246 ops = serial_interface_lookup ("parallel");
38dc5e12
SG
247 else
248 ops = serial_interface_lookup ("hardwire");
4e772f44
SG
249
250 if (!ops)
251 return NULL;
252
253 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
254
255 scb->ops = ops;
256
257 scb->bufcnt = 0;
258 scb->bufp = scb->buf;
259
4febd102 260 if (scb->ops->open(scb, name))
4e772f44
SG
261 {
262 free (scb);
263 return NULL;
264 }
265
4887063b
SG
266 scb->name = strsave (name);
267 scb->next = scb_base;
268 scb->refcnt = 1;
269 scb_base = scb;
270
38dc5e12
SG
271 last_serial_opened = scb;
272
e8f1ad9a
FF
273 if (serial_logfile != NULL)
274 {
275 serial_logfp = fopen (serial_logfile, "w");
276 if (serial_logfp == NULL)
277 {
278 perror_with_name (serial_logfile);
279 }
280 }
281
38dc5e12
SG
282 return scb;
283}
284
285serial_t
4887063b 286serial_fdopen (fd)
38dc5e12
SG
287 const int fd;
288{
289 serial_t scb;
290 struct serial_ops *ops;
291
4887063b
SG
292 for (scb = scb_base; scb; scb = scb->next)
293 if (scb->fd == fd)
294 {
295 scb->refcnt++;
296 return scb;
297 }
298
38dc5e12
SG
299 ops = serial_interface_lookup ("hardwire");
300
301 if (!ops)
302 return NULL;
303
304 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
305
306 scb->ops = ops;
307
308 scb->bufcnt = 0;
309 scb->bufp = scb->buf;
310
311 scb->fd = fd;
312
4887063b
SG
313 scb->name = NULL;
314 scb->next = scb_base;
315 scb->refcnt = 1;
316 scb_base = scb;
317
38dc5e12
SG
318 last_serial_opened = scb;
319
4e772f44
SG
320 return scb;
321}
322
4febd102 323void
bbcc95bd 324serial_close(scb, really_close)
4febd102 325 serial_t scb;
bbcc95bd 326 int really_close;
4febd102 327{
4887063b
SG
328 serial_t tmp_scb;
329
38dc5e12
SG
330 last_serial_opened = NULL;
331
e8f1ad9a
FF
332 if (serial_logfp)
333 {
334 if (serial_reading || serial_writing)
335 {
0db5a6fe 336 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
337 serial_reading = 0;
338 serial_writing = 0;
339 }
340 fclose (serial_logfp);
341 serial_logfp = NULL;
342 }
343
a037b21e
SG
344/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
345 should fix your code instead. */
346
347 if (!scb)
348 return;
349
4887063b
SG
350 scb->refcnt--;
351 if (scb->refcnt > 0)
352 return;
353
bbcc95bd
PS
354 if (really_close)
355 scb->ops->close (scb);
4887063b
SG
356
357 if (scb->name)
358 free (scb->name);
359
360 if (scb_base == scb)
361 scb_base = scb_base->next;
362 else
363 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
364 {
365 if (tmp_scb->next != scb)
366 continue;
367
368 tmp_scb->next = tmp_scb->next->next;
369 break;
370 }
371
a037b21e 372 free(scb);
4febd102
SG
373}
374
4e772f44 375#if 0
bf3b8abd
JK
376/*
377The connect command is #if 0 because I hadn't thought of an elegant
378way to wait for I/O on two serial_t's simultaneously. Two solutions
379came to mind:
380
381 1) Fork, and have have one fork handle the to user direction,
382 and have the other hand the to target direction. This
383 obviously won't cut it for MSDOS.
384
385 2) Use something like select. This assumes that stdin and
386 the target side can both be waited on via the same
387 mechanism. This may not be true for DOS, if GDB is
388 talking to the target via a TCP socket.
389-grossman, 8 Jun 93
390*/
38dc5e12 391
4e772f44
SG
392/* Connect the user directly to the remote system. This command acts just like
393 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
394
38dc5e12
SG
395static serial_t tty_desc; /* Controlling terminal */
396
4e772f44
SG
397static void
398cleanup_tty(ttystate)
38dc5e12 399 serial_ttystate ttystate;
4e772f44 400{
199b2450 401 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
38dc5e12
SG
402 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
403 free (ttystate);
404 SERIAL_CLOSE (tty_desc);
4e772f44
SG
405}
406
407static void
408connect_command (args, fromtty)
409 char *args;
410 int fromtty;
411{
4e772f44
SG
412 int c;
413 char cur_esc = 0;
38dc5e12
SG
414 serial_ttystate ttystate;
415 serial_t port_desc; /* TTY port */
4e772f44
SG
416
417 dont_repeat();
418
4e772f44 419 if (args)
199b2450 420 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
4e772f44 421
199b2450 422 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
4e772f44 423
38dc5e12
SG
424 tty_desc = SERIAL_FDOPEN (0);
425 port_desc = last_serial_opened;
4e772f44 426
38dc5e12 427 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
4e772f44 428
38dc5e12
SG
429 SERIAL_RAW (tty_desc);
430 SERIAL_RAW (port_desc);
431
432 make_cleanup (cleanup_tty, ttystate);
4e772f44
SG
433
434 while (1)
435 {
38dc5e12 436 int mask;
4e772f44 437
38dc5e12 438 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
4e772f44 439
38dc5e12
SG
440 if (mask & 2)
441 { /* tty input */
4e772f44
SG
442 char cx;
443
38dc5e12 444 while (1)
4e772f44 445 {
38dc5e12
SG
446 c = SERIAL_READCHAR(tty_desc, 0);
447
448 if (c == SERIAL_TIMEOUT)
449 break;
450
451 if (c < 0)
452 perror_with_name("connect");
453
454 cx = c;
455 SERIAL_WRITE(port_desc, &cx, 1);
456
457 switch (cur_esc)
458 {
459 case 0:
460 if (c == '\r')
461 cur_esc = c;
462 break;
463 case '\r':
464 if (c == '~')
465 cur_esc = c;
466 else
467 cur_esc = 0;
468 break;
469 case '~':
470 if (c == '.' || c == '\004')
471 return;
472 else
473 cur_esc = 0;
474 }
4e772f44
SG
475 }
476 }
477
38dc5e12
SG
478 if (mask & 1)
479 { /* Port input */
480 char cx;
481
4e772f44
SG
482 while (1)
483 {
38dc5e12
SG
484 c = SERIAL_READCHAR(port_desc, 0);
485
486 if (c == SERIAL_TIMEOUT)
487 break;
488
4e772f44 489 if (c < 0)
38dc5e12
SG
490 perror_with_name("connect");
491
492 cx = c;
493
494 SERIAL_WRITE(tty_desc, &cx, 1);
4e772f44 495 }
4e772f44
SG
496 }
497 }
498}
976bb0be 499#endif /* 0 */
4e772f44 500
5c8ba017
SG
501/* VARARGS */
502void
503#ifdef ANSI_PROTOTYPES
504serial_printf (serial_t desc, const char *format, ...)
505#else
506serial_printf (va_alist)
507 va_dcl
508#endif
509{
510 va_list args;
511 char *buf;
512#ifdef ANSI_PROTOTYPES
513 va_start (args, format);
514#else
515 serial_t desc;
516 char *format;
517
518 va_start (args);
519 desc = va_arg (args, serial_t);
520 format = va_arg (args, char *);
521#endif
522
523 vasprintf (&buf, format, args);
524 SERIAL_WRITE (desc, buf, strlen (buf));
525
526 free (buf);
527 va_end (args);
528}
529
4e772f44
SG
530void
531_initialize_serial ()
532{
d9951af4
SG
533 struct cmd_list_element *cmd;
534
976bb0be 535#if 0
4e772f44
SG
536 add_com ("connect", class_obscure, connect_command,
537 "Connect the terminal directly up to the command monitor.\n\
538Use <CR>~. or <CR>~^D to break out.");
38dc5e12 539#endif /* 0 */
e8f1ad9a
FF
540
541 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
542 var_filename, (char *)&serial_logfile,
543 "Set filename for remote session recording.\n\
544This file is used to record the remote session for future playback\n\
545by gdbserver.", &setlist),
546 &showlist);
547
d9951af4
SG
548 add_show_from_set (add_set_enum_cmd ("remotelogbase", no_class,
549 logbase_enums,
550 (char *)&serial_logbase,
551 "Set ...",
552 &setlist),
553 &showlist);
976bb0be 554}
This page took 0.349466 seconds and 4 git commands to generate.