* gencode.c (build_instruction) [MUL]: Cast operands to word64, to
[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 static char *serial_logfile = NULL;
42 static FILE *serial_logfp = NULL;
43
44 static struct serial_ops *serial_interface_lookup PARAMS ((char *));
45 static void serial_logchar PARAMS ((int ch, int timeout));
46 static char logbase_hex[] = "hex";
47 static char logbase_octal[] = "octal";
48 static char logbase_ascii[] = "ascii";
49 static char *logbase_enums[] = {logbase_hex, logbase_octal, logbase_ascii, NULL};
50 static char *serial_logbase = logbase_ascii;
51
52 \f
53 static int serial_reading = 0;
54 static int serial_writing = 0;
55
56 void
57 serial_log_command (cmd)
58 const char *cmd;
59 {
60 if (!serial_logfp)
61 return;
62
63 if (serial_reading || serial_writing)
64 {
65 fputc_unfiltered ('\n', serial_logfp);
66 serial_reading = 0;
67 serial_writing = 0;
68 }
69 fprintf_unfiltered (serial_logfp, "c %s\n", cmd);
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
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
79 static void
80 serial_logchar (ch, timeout)
81 int ch;
82 int timeout;
83 {
84 if (serial_logbase != logbase_ascii)
85 fputc_unfiltered (' ', serial_logfp);
86
87 switch (ch)
88 {
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 }
119 }
120
121 int
122 serial_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 {
133 fputc_unfiltered ('\n', serial_logfp);
134 serial_reading = 0;
135 }
136 if (!serial_writing)
137 {
138 fputs_unfiltered ("w ", serial_logfp);
139 serial_writing = 1;
140 }
141 for (count = 0; count < len; count++)
142 {
143 serial_logchar (str[count] & 0xff, 0);
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
152 int
153 serial_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 {
164 fputc_unfiltered ('\n', serial_logfp);
165 serial_writing = 0;
166 }
167 if (!serial_reading)
168 {
169 fputs_unfiltered ("r ", serial_logfp);
170 serial_reading = 1;
171 }
172 serial_logchar (ch, timeout);
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
180 int
181 serial_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
204 static struct serial_ops *
205 serial_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
217 void
218 serial_add_interface(optable)
219 struct serial_ops *optable;
220 {
221 optable->next = serial_ops_list;
222 serial_ops_list = optable;
223 }
224
225 /* Open up a device or a network socket, depending upon the syntax of NAME. */
226
227 serial_t
228 serial_open (name)
229 const char *name;
230 {
231 serial_t scb;
232 struct serial_ops *ops;
233
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
241 if (strcmp (name, "pc") == 0)
242 ops = serial_interface_lookup ("pc");
243 else if (strchr (name, ':'))
244 ops = serial_interface_lookup ("tcp");
245 else if (strncmp (name, "lpt", 3) == 0)
246 ops = serial_interface_lookup ("parallel");
247 else
248 ops = serial_interface_lookup ("hardwire");
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
260 if (scb->ops->open(scb, name))
261 {
262 free (scb);
263 return NULL;
264 }
265
266 scb->name = strsave (name);
267 scb->next = scb_base;
268 scb->refcnt = 1;
269 scb_base = scb;
270
271 last_serial_opened = scb;
272
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
282 return scb;
283 }
284
285 serial_t
286 serial_fdopen (fd)
287 const int fd;
288 {
289 serial_t scb;
290 struct serial_ops *ops;
291
292 for (scb = scb_base; scb; scb = scb->next)
293 if (scb->fd == fd)
294 {
295 scb->refcnt++;
296 return scb;
297 }
298
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
313 scb->name = NULL;
314 scb->next = scb_base;
315 scb->refcnt = 1;
316 scb_base = scb;
317
318 last_serial_opened = scb;
319
320 return scb;
321 }
322
323 void
324 serial_close(scb, really_close)
325 serial_t scb;
326 int really_close;
327 {
328 serial_t tmp_scb;
329
330 last_serial_opened = NULL;
331
332 if (serial_logfp)
333 {
334 if (serial_reading || serial_writing)
335 {
336 fputc_unfiltered ('\n', serial_logfp);
337 serial_reading = 0;
338 serial_writing = 0;
339 }
340 fclose (serial_logfp);
341 serial_logfp = NULL;
342 }
343
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
350 scb->refcnt--;
351 if (scb->refcnt > 0)
352 return;
353
354 if (really_close)
355 scb->ops->close (scb);
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
372 free(scb);
373 }
374
375 #if 0
376 /*
377 The connect command is #if 0 because I hadn't thought of an elegant
378 way to wait for I/O on two serial_t's simultaneously. Two solutions
379 came 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 */
391
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
395 static serial_t tty_desc; /* Controlling terminal */
396
397 static void
398 cleanup_tty(ttystate)
399 serial_ttystate ttystate;
400 {
401 printf_unfiltered ("\r\n[Exiting connect mode]\r\n");
402 SERIAL_SET_TTY_STATE (tty_desc, ttystate);
403 free (ttystate);
404 SERIAL_CLOSE (tty_desc);
405 }
406
407 static void
408 connect_command (args, fromtty)
409 char *args;
410 int fromtty;
411 {
412 int c;
413 char cur_esc = 0;
414 serial_ttystate ttystate;
415 serial_t port_desc; /* TTY port */
416
417 dont_repeat();
418
419 if (args)
420 fprintf_unfiltered(gdb_stderr, "This command takes no args. They have been ignored.\n");
421
422 printf_unfiltered("[Entering connect mode. Use ~. or ~^D to escape]\n");
423
424 tty_desc = SERIAL_FDOPEN (0);
425 port_desc = last_serial_opened;
426
427 ttystate = SERIAL_GET_TTY_STATE (tty_desc);
428
429 SERIAL_RAW (tty_desc);
430 SERIAL_RAW (port_desc);
431
432 make_cleanup (cleanup_tty, ttystate);
433
434 while (1)
435 {
436 int mask;
437
438 mask = SERIAL_WAIT_2 (tty_desc, port_desc, -1);
439
440 if (mask & 2)
441 { /* tty input */
442 char cx;
443
444 while (1)
445 {
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 }
475 }
476 }
477
478 if (mask & 1)
479 { /* Port input */
480 char cx;
481
482 while (1)
483 {
484 c = SERIAL_READCHAR(port_desc, 0);
485
486 if (c == SERIAL_TIMEOUT)
487 break;
488
489 if (c < 0)
490 perror_with_name("connect");
491
492 cx = c;
493
494 SERIAL_WRITE(tty_desc, &cx, 1);
495 }
496 }
497 }
498 }
499 #endif /* 0 */
500
501 /* VARARGS */
502 void
503 #ifdef ANSI_PROTOTYPES
504 serial_printf (serial_t desc, const char *format, ...)
505 #else
506 serial_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
530 void
531 _initialize_serial ()
532 {
533 struct cmd_list_element *cmd;
534
535 #if 0
536 add_com ("connect", class_obscure, connect_command,
537 "Connect the terminal directly up to the command monitor.\n\
538 Use <CR>~. or <CR>~^D to break out.");
539 #endif /* 0 */
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\
544 This file is used to record the remote session for future playback\n\
545 by gdbserver.", &setlist),
546 &showlist);
547
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);
554 }
This page took 0.093613 seconds and 4 git commands to generate.