* coff-h8300.c (h8300_reloc16_extra_cases): Make name a const
[deliverable/binutils-gdb.git] / gdb / serial.c
1 /* Generic serial interface routines
2 Copyright 1992, 1993, 1996 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, Boston, MA 02111-1307, USA. */
19
20 #include "defs.h"
21 #include <ctype.h>
22 #include "serial.h"
23 #include "gdb_string.h"
24 #include "gdbcmd.h"
25
26 /* Linked list of serial I/O handlers */
27
28 static struct serial_ops *serial_ops_list = NULL;
29
30 /* This is the last serial stream opened. Used by connect command. */
31
32 static serial_t last_serial_opened = NULL;
33
34 /* Pointer to list of scb's. */
35
36 static serial_t scb_base;
37
38 /* Non-NULL gives filename which contains a recording of the remote session,
39 suitable for playback by gdbserver. */
40
41 char *serial_logfile = NULL;
42 FILE *serial_logfp = NULL;
43
44 \f
45 static int serial_reading = 0;
46 static int serial_writing = 0;
47
48 void
49 serial_log_command (cmd)
50 const char *cmd;
51 {
52 if (serial_reading || serial_writing)
53 {
54 fputc_unfiltered ('\n', serial_logfp);
55 serial_reading = 0;
56 serial_writing = 0;
57 }
58 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
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
64 static void
65 serial_logchar (ch)
66 int ch;
67 {
68 switch (ch)
69 {
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;
78 }
79 }
80
81 int
82 serial_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 {
93 fputc_unfiltered ('\n', serial_logfp);
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
113 int
114 serial_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 {
125 fputc_unfiltered ('\n', serial_logfp);
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
142 static struct serial_ops *
143 serial_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
155 void
156 serial_add_interface(optable)
157 struct serial_ops *optable;
158 {
159 optable->next = serial_ops_list;
160 serial_ops_list = optable;
161 }
162
163 /* Open up a device or a network socket, depending upon the syntax of NAME. */
164
165 serial_t
166 serial_open (name)
167 const char *name;
168 {
169 serial_t scb;
170 struct serial_ops *ops;
171
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
179 if (strcmp (name, "pc") == 0)
180 ops = serial_interface_lookup ("pc");
181 else if (strchr (name, ':'))
182 ops = serial_interface_lookup ("tcp");
183 else if (strncmp (name, "lpt", 3) == 0)
184 ops = serial_interface_lookup ("parallel");
185 else
186 ops = serial_interface_lookup ("hardwire");
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
198 if (scb->ops->open(scb, name))
199 {
200 free (scb);
201 return NULL;
202 }
203
204 scb->name = strsave (name);
205 scb->next = scb_base;
206 scb->refcnt = 1;
207 scb_base = scb;
208
209 last_serial_opened = scb;
210
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
220 return scb;
221 }
222
223 serial_t
224 serial_fdopen (fd)
225 const int fd;
226 {
227 serial_t scb;
228 struct serial_ops *ops;
229
230 for (scb = scb_base; scb; scb = scb->next)
231 if (scb->fd == fd)
232 {
233 scb->refcnt++;
234 return scb;
235 }
236
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
251 scb->name = NULL;
252 scb->next = scb_base;
253 scb->refcnt = 1;
254 scb_base = scb;
255
256 last_serial_opened = scb;
257
258 return scb;
259 }
260
261 void
262 serial_close(scb, really_close)
263 serial_t scb;
264 int really_close;
265 {
266 serial_t tmp_scb;
267
268 last_serial_opened = NULL;
269
270 if (serial_logfp)
271 {
272 if (serial_reading || serial_writing)
273 {
274 fputc_unfiltered ('\n', serial_logfp);
275 serial_reading = 0;
276 serial_writing = 0;
277 }
278 fclose (serial_logfp);
279 serial_logfp = NULL;
280 }
281
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
288 scb->refcnt--;
289 if (scb->refcnt > 0)
290 return;
291
292 if (really_close)
293 scb->ops->close (scb);
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
310 free(scb);
311 }
312
313 #if 0
314 /*
315 The connect command is #if 0 because I hadn't thought of an elegant
316 way to wait for I/O on two serial_t's simultaneously. Two solutions
317 came 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 */
329
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
333 static serial_t tty_desc; /* Controlling terminal */
334
335 static void
336 cleanup_tty(ttystate)
337 serial_ttystate ttystate;
338 {
339 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
340 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
341 free (ttystate);
342 SERIAL_CLOSE (tty_desc);
343 }
344
345 static void
346 connect_command (args, fromtty)
347 char *args;
348 int fromtty;
349 {
350 int c;
351 char cur_esc = 0;
352 serial_ttystate ttystate;
353 serial_t port_desc; /* TTY port */
354
355 dont_repeat();
356
357 if (args)
358 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
359
360 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
361
362 tty_desc = SERIAL_FDOPEN (0);
363 port_desc = last_serial_opened;
364
365 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
366
367 SERIAL_RAW (tty_desc);
368 SERIAL_RAW (port_desc);
369
370 make_cleanup (cleanup_tty, ttystate);
371
372 while (1)
373 {
374 int mask;
375
376 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
377
378 if (mask & 2)
379 { /* tty input */
380 char cx;
381
382 while (1)
383 {
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 }
413 }
414 }
415
416 if (mask & 1)
417 { /* Port input */
418 char cx;
419
420 while (1)
421 {
422 c = SERIAL_READCHAR(port_desc, 0);
423
424 if (c == SERIAL_TIMEOUT)
425 break;
426
427 if (c < 0)
428 perror_with_name("connect");
429
430 cx = c;
431
432 SERIAL_WRITE(tty_desc, &cx, 1);
433 }
434 }
435 }
436 }
437 #endif /* 0 */
438
439 /* VARARGS */
440 void
441 #ifdef ANSI_PROTOTYPES
442 serial_printf (serial_t desc, const char *format, ...)
443 #else
444 serial_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
468 void
469 _initialize_serial ()
470 {
471 #if 0
472 add_com ("connect", class_obscure, connect_command,
473 "Connect the terminal directly up to the command monitor.\n\
474 Use <CR>~. or <CR>~^D to break out.");
475 #endif /* 0 */
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\
480 This file is used to record the remote session for future playback\n\
481 by gdbserver.", &setlist),
482 &showlist);
483
484 }
This page took 0.05931 seconds and 4 git commands to generate.