* ldlang.c (dprint_statement): Stop printing at end of list.
[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
41char *serial_logfile = NULL;
42FILE *serial_logfp = NULL;
43
44\f
45static int serial_reading = 0;
46static int serial_writing = 0;
47
48void
49serial_log_command (cmd)
50 const char *cmd;
51{
52 if (serial_reading || serial_writing)
53 {
0db5a6fe 54 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
55 serial_reading = 0;
56 serial_writing = 0;
57 }
0db5a6fe 58 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
e8f1ad9a
FF
59 /* Make sure that the log file is as up-to-date as possible,
60 in case we are getting ready to dump core or something. */
61 fflush (serial_logfp);
62}
63
64static void
65serial_logchar (ch)
66 int ch;
67{
68 switch (ch)
69 {
0db5a6fe
FF
70 case '\\': fputs_unfiltered ("\\\\", serial_logfp); break;
71 case '\b': fputs_unfiltered ("\\b", serial_logfp); break;
72 case '\f': fputs_unfiltered ("\\f", serial_logfp); break;
73 case '\n': fputs_unfiltered ("\\n", serial_logfp); break;
74 case '\r': fputs_unfiltered ("\\r", serial_logfp); break;
75 case '\t': fputs_unfiltered ("\\t", serial_logfp); break;
76 case '\v': fputs_unfiltered ("\\v", serial_logfp); break;
77 default: fprintf_unfiltered (serial_logfp, isprint (ch) ? "%c" : "\\x%02x", ch & 0xFF); break;
e8f1ad9a
FF
78 }
79}
80
81int
82serial_write (scb, str, len)
83 serial_t scb;
84 const char *str;
85 int len;
86{
87 int count;
88
89 if (serial_logfp != NULL)
90 {
91 if (serial_reading)
92 {
0db5a6fe 93 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
94 serial_reading = 0;
95 }
96 if (!serial_writing)
97 {
98 serial_logchar ('w');
99 serial_logchar (' ');
100 serial_writing = 1;
101 }
102 for (count = 0; count < len; count++)
103 {
104 serial_logchar (str[count]);
105 }
106 /* Make sure that the log file is as up-to-date as possible,
107 in case we are getting ready to dump core or something. */
108 fflush (serial_logfp);
109 }
110 return (scb -> ops -> write (scb, str, len));
111}
112
113int
114serial_readchar (scb, timeout)
115 serial_t scb;
116 int timeout;
117{
118 int ch;
119
120 ch = scb -> ops -> readchar (scb, timeout);
121 if (serial_logfp != NULL)
122 {
123 if (serial_writing)
124 {
0db5a6fe 125 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
126 serial_writing = 0;
127 }
128 if (!serial_reading)
129 {
130 serial_logchar ('r');
131 serial_logchar (' ');
132 serial_reading = 1;
133 }
134 serial_logchar (ch);
135 /* Make sure that the log file is as up-to-date as possible,
136 in case we are getting ready to dump core or something. */
137 fflush (serial_logfp);
138 }
139 return (ch);
140}
141
4e772f44
SG
142static struct serial_ops *
143serial_interface_lookup (name)
144 char *name;
145{
146 struct serial_ops *ops;
147
148 for (ops = serial_ops_list; ops; ops = ops->next)
149 if (strcmp (name, ops->name) == 0)
150 return ops;
151
152 return NULL;
153}
154
155void
156serial_add_interface(optable)
157 struct serial_ops *optable;
158{
159 optable->next = serial_ops_list;
160 serial_ops_list = optable;
161}
162
38dc5e12
SG
163/* Open up a device or a network socket, depending upon the syntax of NAME. */
164
4e772f44 165serial_t
55679787 166serial_open (name)
4e772f44
SG
167 const char *name;
168{
169 serial_t scb;
170 struct serial_ops *ops;
171
4887063b
SG
172 for (scb = scb_base; scb; scb = scb->next)
173 if (scb->name && strcmp (scb->name, name) == 0)
174 {
175 scb->refcnt++;
176 return scb;
177 }
178
55679787
SC
179 if (strcmp (name, "pc") == 0)
180 ops = serial_interface_lookup ("pc");
181 else if (strchr (name, ':'))
38dc5e12 182 ops = serial_interface_lookup ("tcp");
c84e5000
SC
183 else if (strncmp (name, "lpt", 3) == 0)
184 ops = serial_interface_lookup ("parallel");
38dc5e12
SG
185 else
186 ops = serial_interface_lookup ("hardwire");
4e772f44
SG
187
188 if (!ops)
189 return NULL;
190
191 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
192
193 scb->ops = ops;
194
195 scb->bufcnt = 0;
196 scb->bufp = scb->buf;
197
4febd102 198 if (scb->ops->open(scb, name))
4e772f44
SG
199 {
200 free (scb);
201 return NULL;
202 }
203
4887063b
SG
204 scb->name = strsave (name);
205 scb->next = scb_base;
206 scb->refcnt = 1;
207 scb_base = scb;
208
38dc5e12
SG
209 last_serial_opened = scb;
210
e8f1ad9a
FF
211 if (serial_logfile != NULL)
212 {
213 serial_logfp = fopen (serial_logfile, "w");
214 if (serial_logfp == NULL)
215 {
216 perror_with_name (serial_logfile);
217 }
218 }
219
38dc5e12
SG
220 return scb;
221}
222
223serial_t
4887063b 224serial_fdopen (fd)
38dc5e12
SG
225 const int fd;
226{
227 serial_t scb;
228 struct serial_ops *ops;
229
4887063b
SG
230 for (scb = scb_base; scb; scb = scb->next)
231 if (scb->fd == fd)
232 {
233 scb->refcnt++;
234 return scb;
235 }
236
38dc5e12
SG
237 ops = serial_interface_lookup ("hardwire");
238
239 if (!ops)
240 return NULL;
241
242 scb = (serial_t)xmalloc (sizeof (struct _serial_t));
243
244 scb->ops = ops;
245
246 scb->bufcnt = 0;
247 scb->bufp = scb->buf;
248
249 scb->fd = fd;
250
4887063b
SG
251 scb->name = NULL;
252 scb->next = scb_base;
253 scb->refcnt = 1;
254 scb_base = scb;
255
38dc5e12
SG
256 last_serial_opened = scb;
257
4e772f44
SG
258 return scb;
259}
260
4febd102 261void
bbcc95bd 262serial_close(scb, really_close)
4febd102 263 serial_t scb;
bbcc95bd 264 int really_close;
4febd102 265{
4887063b
SG
266 serial_t tmp_scb;
267
38dc5e12
SG
268 last_serial_opened = NULL;
269
e8f1ad9a
FF
270 if (serial_logfp)
271 {
272 if (serial_reading || serial_writing)
273 {
0db5a6fe 274 fputc_unfiltered ('\n', serial_logfp);
e8f1ad9a
FF
275 serial_reading = 0;
276 serial_writing = 0;
277 }
278 fclose (serial_logfp);
279 serial_logfp = NULL;
280 }
281
a037b21e
SG
282/* This is bogus. It's not our fault if you pass us a bad scb...! Rob, you
283 should fix your code instead. */
284
285 if (!scb)
286 return;
287
4887063b
SG
288 scb->refcnt--;
289 if (scb->refcnt > 0)
290 return;
291
bbcc95bd
PS
292 if (really_close)
293 scb->ops->close (scb);
4887063b
SG
294
295 if (scb->name)
296 free (scb->name);
297
298 if (scb_base == scb)
299 scb_base = scb_base->next;
300 else
301 for (tmp_scb = scb_base; tmp_scb; tmp_scb = tmp_scb->next)
302 {
303 if (tmp_scb->next != scb)
304 continue;
305
306 tmp_scb->next = tmp_scb->next->next;
307 break;
308 }
309
a037b21e 310 free(scb);
4febd102
SG
311}
312
4e772f44 313#if 0
bf3b8abd
JK
314/*
315The connect command is #if 0 because I hadn't thought of an elegant
316way to wait for I/O on two serial_t's simultaneously. Two solutions
317came to mind:
318
319 1) Fork, and have have one fork handle the to user direction,
320 and have the other hand the to target direction. This
321 obviously won't cut it for MSDOS.
322
323 2) Use something like select. This assumes that stdin and
324 the target side can both be waited on via the same
325 mechanism. This may not be true for DOS, if GDB is
326 talking to the target via a TCP socket.
327-grossman, 8 Jun 93
328*/
38dc5e12 329
4e772f44
SG
330/* Connect the user directly to the remote system. This command acts just like
331 the 'cu' or 'tip' command. Use <CR>~. or <CR>~^D to break out. */
332
38dc5e12
SG
333static serial_t tty_desc; /* Controlling terminal */
334
4e772f44
SG
335static void
336cleanup_tty(ttystate)
38dc5e12 337 serial_ttystate ttystate;
4e772f44 338{
199b2450 339 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
38dc5e12
SG
340 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
341 free (ttystate);
342 SERIAL_CLOSE (tty_desc);
4e772f44
SG
343}
344
345static void
346connect_command (args, fromtty)
347 char *args;
348 int fromtty;
349{
4e772f44
SG
350 int c;
351 char cur_esc = 0;
38dc5e12
SG
352 serial_ttystate ttystate;
353 serial_t port_desc; /* TTY port */
4e772f44
SG
354
355 dont_repeat();
356
4e772f44 357 if (args)
199b2450 358 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
4e772f44 359
199b2450 360 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
4e772f44 361
38dc5e12
SG
362 tty_desc = SERIAL_FDOPEN (0);
363 port_desc = last_serial_opened;
4e772f44 364
38dc5e12 365 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
4e772f44 366
38dc5e12
SG
367 SERIAL_RAW (tty_desc);
368 SERIAL_RAW (port_desc);
369
370 make_cleanup (cleanup_tty, ttystate);
4e772f44
SG
371
372 while (1)
373 {
38dc5e12 374 int mask;
4e772f44 375
38dc5e12 376 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
4e772f44 377
38dc5e12
SG
378 if (mask & 2)
379 { /* tty input */
4e772f44
SG
380 char cx;
381
38dc5e12 382 while (1)
4e772f44 383 {
38dc5e12
SG
384 c = SERIAL_READCHAR(tty_desc, 0);
385
386 if (c == SERIAL_TIMEOUT)
387 break;
388
389 if (c < 0)
390 perror_with_name("connect");
391
392 cx = c;
393 SERIAL_WRITE(port_desc, &cx, 1);
394
395 switch (cur_esc)
396 {
397 case 0:
398 if (c == '\r')
399 cur_esc = c;
400 break;
401 case '\r':
402 if (c == '~')
403 cur_esc = c;
404 else
405 cur_esc = 0;
406 break;
407 case '~':
408 if (c == '.' || c == '\004')
409 return;
410 else
411 cur_esc = 0;
412 }
4e772f44
SG
413 }
414 }
415
38dc5e12
SG
416 if (mask & 1)
417 { /* Port input */
418 char cx;
419
4e772f44
SG
420 while (1)
421 {
38dc5e12
SG
422 c = SERIAL_READCHAR(port_desc, 0);
423
424 if (c == SERIAL_TIMEOUT)
425 break;
426
4e772f44 427 if (c < 0)
38dc5e12
SG
428 perror_with_name("connect");
429
430 cx = c;
431
432 SERIAL_WRITE(tty_desc, &cx, 1);
4e772f44 433 }
4e772f44
SG
434 }
435 }
436}
976bb0be 437#endif /* 0 */
4e772f44 438
5c8ba017
SG
439/* VARARGS */
440void
441#ifdef ANSI_PROTOTYPES
442serial_printf (serial_t desc, const char *format, ...)
443#else
444serial_printf (va_alist)
445 va_dcl
446#endif
447{
448 va_list args;
449 char *buf;
450#ifdef ANSI_PROTOTYPES
451 va_start (args, format);
452#else
453 serial_t desc;
454 char *format;
455
456 va_start (args);
457 desc = va_arg (args, serial_t);
458 format = va_arg (args, char *);
459#endif
460
461 vasprintf (&buf, format, args);
462 SERIAL_WRITE (desc, buf, strlen (buf));
463
464 free (buf);
465 va_end (args);
466}
467
4e772f44
SG
468void
469_initialize_serial ()
470{
976bb0be 471#if 0
4e772f44
SG
472 add_com ("connect", class_obscure, connect_command,
473 "Connect the terminal directly up to the command monitor.\n\
474Use <CR>~. or <CR>~^D to break out.");
38dc5e12 475#endif /* 0 */
e8f1ad9a
FF
476
477 add_show_from_set (add_set_cmd ("remotelogfile", no_class,
478 var_filename, (char *)&serial_logfile,
479 "Set filename for remote session recording.\n\
480This file is used to record the remote session for future playback\n\
481by gdbserver.", &setlist),
482 &showlist);
483
976bb0be 484}
This page took 0.210376 seconds and 4 git commands to generate.