From a0f9783ea791ea36875071c35e6d2c4d5f38d34c Mon Sep 17 00:00:00 2001 From: Stu Grossman Date: Tue, 8 Sep 1992 22:46:08 +0000 Subject: [PATCH] * a68v-xdep.c (store_inferior_registers): declare as void. * infptrace.c: HP/Apollos have ptrace.h in the wrong place. * remote-st2000.c: Massive changes to use new serial package. Also added 'connect' command to transparantly connect to serial port. * ser-termios.c: Big cleanup, use nicer coding conventions. * ser-bsd.c: New module, serial stuff for BSD systems. * serial.h: Define struct ttystate properly using HAVE_TERMIO. * xm-apollo68b.h: #define PTRACE_IN_WRONG_PLACE... --- gdb/a68v-xdep.c | 1 + gdb/infptrace.c | 10 +- gdb/remote-st2000.c | 505 +++++++++++++++++++++----------------------- gdb/ser-bsd.c | 228 ++++++++++++++++++++ gdb/ser-termios.c | 252 +++++++++++----------- gdb/serial.h | 33 ++- gdb/xm-apollo68b.h | 4 + 7 files changed, 643 insertions(+), 390 deletions(-) create mode 100644 gdb/ser-bsd.c diff --git a/gdb/a68v-xdep.c b/gdb/a68v-xdep.c index ec272ca1969..d81cbe813c9 100644 --- a/gdb/a68v-xdep.c +++ b/gdb/a68v-xdep.c @@ -141,6 +141,7 @@ fetch_inferior_registers () } /* ARGSUSED */ +void store_inferior_registers (regno) int regno; { diff --git a/gdb/infptrace.c b/gdb/infptrace.c index e9fa66d8555..3856b369438 100644 --- a/gdb/infptrace.c +++ b/gdb/infptrace.c @@ -31,8 +31,12 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #ifndef USG +#ifdef PTRACE_IN_WRONG_PLACE +#include +#else #include #endif +#endif #if !defined (PT_KILL) #define PT_KILL 8 @@ -395,8 +399,7 @@ child_xfer_memory (memaddr, myaddr, len, write, target) /* Copy data to be written over corresponding part of buffer */ - (void) memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, - len); + memcpy ((char *) buffer + (memaddr & (sizeof (int) - 1)), myaddr, len); /* Write the entire buffer. */ @@ -431,8 +434,7 @@ child_xfer_memory (memaddr, myaddr, len, write, target) } /* Copy appropriate bytes out of the buffer. */ - (void) memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), - len); + memcpy (myaddr, (char *) buffer + (memaddr & (sizeof (int) - 1)), len); } return len; } diff --git a/gdb/remote-st2000.c b/gdb/remote-st2000.c index f8a4ef3cd1d..4fddb3cfc57 100644 --- a/gdb/remote-st2000.c +++ b/gdb/remote-st2000.c @@ -36,12 +36,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" #include "gdbcore.h" -#include "terminal.h" #include "target.h" #include "wait.h" #include #include #include +#include +#include "serial.h" extern struct target_ops st2000_ops; /* Forward declaration */ @@ -61,10 +62,6 @@ static int timeout = 24; starts. */ int st2000_desc = -1; -/* stream which is fdopen'd from st2000_desc. Only valid when - st2000_desc != -1. */ -FILE *st2000_stream; - /* Send data to stdebug. Works just like printf. */ static void @@ -73,60 +70,62 @@ printf_stdebug(va_alist) { va_list args; char *pattern; + char buf[200]; va_start(args); pattern = va_arg(args, char *); - vfprintf(st2000_stream, pattern, args); - fflush(st2000_stream); + vsprintf(buf, pattern, args); + if (!serial_write(buf, strlen(buf))) + fprintf(stderr, "serial_write failed: %s\n", safe_strerror(errno)); } /* Read a character from the remote system, doing all the fancy timeout stuff. */ static int -readchar () +readchar(timeout) + int timeout; { - char buf; - - buf = '\0'; -#ifdef HAVE_TERMIO - /* termio does the timeout for us. */ - read (st2000_desc, &buf, 1); -#else - alarm (timeout); - if (read (st2000_desc, &buf, 1) < 0) + int c; + + c = serial_readchar(timeout); + +#ifdef LOG_FILE + putc(c & 0x7f, log_file); +#endif + + if (c >= 0) + return c & 0x7f; + + if (c == -2) { - if (errno == EINTR) - error ("Timeout reading from remote system."); - else - perror_with_name ("remote"); + if (timeout == 0) + return c; /* Polls shouldn't generate timeout errors */ + + error("Timeout reading from remote system."); } - alarm (0); -#endif - if (buf == '\0') - error ("Timeout reading from remote system."); -#if defined (LOG_FILE) - putc (buf & 0x7f, log_file); -#endif - return buf & 0x7f; + perror_with_name("remote-st2000"); } -/* Keep discarding input from the remote system, until STRING is found. +/* Scan input from the remote system, until STRING is found. If DISCARD is + non-zero, then discard non-matching input, else print it out. Let the user break out immediately. */ static void -expect (string) +expect(string, discard) char *string; + int discard; { char *p = string; + int c; immediate_quit = 1; while (1) { - if (readchar() == *p) + c = readchar(timeout); + if (c == *p++) { - p++; if (*p == '\0') { immediate_quit = 0; @@ -134,7 +133,15 @@ expect (string) } } else - p = string; + { + if (!discard) + { + fwrite(string, 1, (p - 1) - string, stdout); + putchar((char)c); + fflush(stdout); + } + p = string; + } } } @@ -153,26 +160,27 @@ expect (string) necessary to prevent getting into states from which we can't recover. */ static void -expect_prompt () +expect_prompt(discard) + int discard; { #if defined (LOG_FILE) /* This is a convenient place to do this. The idea is to do it often enough that we never lose much data if we terminate abnormally. */ - fflush (log_file); + fflush(log_file); #endif - expect ("dbug> "); + expect ("dbug> ", discard); } /* Get a hex digit from the remote system & return its value. If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */ static int -get_hex_digit (ignore_space) +get_hex_digit(ignore_space) int ignore_space; { int ch; while (1) { - ch = readchar (); + ch = readchar(timeout); if (ch >= '0' && ch <= '9') return ch - '0'; else if (ch >= 'A' && ch <= 'F') @@ -183,13 +191,13 @@ get_hex_digit (ignore_space) ; else { - expect_prompt (); - error ("Invalid hex digit from remote system."); + expect_prompt(1); + error("Invalid hex digit from remote system."); } } } -/* Get a byte from st2000_desc and put it in *BYT. Accept any number +/* Get a byte from stdebug and put it in *BYT. Accept any number leading spaces. */ static void get_hex_byte (byt) @@ -223,21 +231,6 @@ get_hex_regs (n, regno) } } -/* Called when SIGALRM signal sent due to alarm() timeout. */ -#ifndef HAVE_TERMIO - -#ifndef __STDC__ -#define volatile /**/ -#endif -volatile int n_alarms; - -static void -st2000_timer () -{ - n_alarms++; -} -#endif - /* This is called not only when we first attach, but also when the user types "run" after having attached. */ static void @@ -249,10 +242,10 @@ st2000_create_inferior (execfile, args, env) int entry_pt; if (args && *args) - error ("Can't pass arguments to remote STDEBUG process"); + error("Can't pass arguments to remote STDEBUG process"); if (execfile == 0 || exec_bfd == 0) - error ("No exec file specified"); + error("No exec file specified"); entry_pt = (int) bfd_get_start_address (exec_bfd); @@ -279,128 +272,35 @@ st2000_create_inferior (execfile, args, env) proceed ((CORE_ADDR)entry_pt, -1, 0); /* Let 'er rip... */ } -/* Translate baud rates from integers to damn B_codes. Unix should - have outgrown this crap years ago, but even POSIX wouldn't buck it. */ - -#ifndef B19200 -#define B19200 EXTA -#endif -#ifndef B38400 -#define B38400 EXTB -#endif - -static struct {int rate, damn_b;} baudtab[] = { - {0, B0}, - {50, B50}, - {75, B75}, - {110, B110}, - {134, B134}, - {150, B150}, - {200, B200}, - {300, B300}, - {600, B600}, - {1200, B1200}, - {1800, B1800}, - {2400, B2400}, - {4800, B4800}, - {9600, B9600}, - {19200, B19200}, - {38400, B38400}, - {-1, -1}, -}; - -static int -damn_b (rate) - int rate; -{ - int i; - - for (i = 0; baudtab[i].rate != -1; i++) - if (rate == baudtab[i].rate) return baudtab[i].damn_b; - return B38400; /* Random */ -} - - /* Open a connection to a remote debugger. NAME is the filename used for communication. */ static int baudrate = 9600; -static char *dev_name; - -static TERMINAL old_sg; +static char dev_name[100]; static void -st2000_open (name, from_tty) - char *name; +st2000_open(args, from_tty) + char *args; int from_tty; { - TERMINAL sg; - - char *p; + int n; + char junk[100]; - target_preopen (from_tty); - - if (!name) - goto erroid; - - /* Find the first whitespace character, it separates dev_name from - the baud rate. */ - - for (p = name; *p && !isspace (*p); p++) - ; - if (*p == '\0') -erroid: - error ("\ -Please include the name of the device for the serial port, and the baud rate."); - - dev_name = alloca (p - name + 1); - strncpy (dev_name, name, p - name); - dev_name[p - name] = '\0'; - - /* Skip over the whitespace after dev_name */ - for (; isspace (*p); p++) - /*EMPTY*/; + target_preopen(from_tty); - if (1 != sscanf (p, "%d ", &baudrate)) - goto erroid; + n = sscanf(args, " %s %d %s", dev_name, &baudrate, junk); - st2000_close (0); + if (n != 2) + error("Bad arguments. Usage: target st2000 \n\ +or target st2000 \n"); - st2000_desc = open (dev_name, O_RDWR); - if (st2000_desc < 0) - perror_with_name (dev_name); - ioctl (st2000_desc, TIOCGETP, &sg); - old_sg = sg; - -#ifdef HAVE_TERMIO - sg.c_cc[VMIN] = 0; /* read with timeout. */ - sg.c_cc[VTIME] = timeout * 10; - sg.c_lflag &= ~(ICANON | ECHO); - sg.c_cflag = (sg.c_cflag & ~CBAUD) | damn_b (baudrate); -#else - sg.sg_ispeed = damn_b (baudrate); - sg.sg_ospeed = damn_b (baudrate); - sg.sg_flags |= RAW | ANYP; - sg.sg_flags &= ~ECHO; -#endif + st2000_close(0); - ioctl (st2000_desc, TIOCSETP, &sg); - st2000_stream = fdopen (st2000_desc, "r+"); + st2000_desc = serial_open(dev_name); - push_target (&st2000_ops); + serial_setbaudrate(baudrate); -#ifndef HAVE_TERMIO -#ifndef NO_SIGINTERRUPT - /* Cause SIGALRM's to make reads fail with EINTR instead of resuming - the read. */ - if (siginterrupt (SIGALRM, 1) != 0) - perror ("st2000_open: error in siginterrupt"); -#endif - - /* Set up read timeout timer. */ - if ((void (*)) signal (SIGALRM, st2000_timer) == (void (*)) -1) - perror ("st2000_open: error in signal"); -#endif + push_target(&st2000_ops); #if defined (LOG_FILE) log_file = fopen (LOG_FILE, "w"); @@ -409,13 +309,13 @@ Please include the name of the device for the serial port, and the baud rate."); #endif /* Hello? Are you there? */ - printf_stdebug ("\r"); + printf_stdebug("\003"); /* ^C wakes up dbug */ - expect_prompt (); + expect_prompt(1); if (from_tty) - printf ("Remote %s connected to %s\n", target_shortname, - dev_name); + printf("Remote %s connected to %s\n", target_shortname, + dev_name); } /* Close out all files and local state before this target loses control. */ @@ -424,27 +324,14 @@ static void st2000_close (quitting) int quitting; { - - /* Reset the terminal to its original settings. */ - - ioctl (st2000_desc, TIOCSETP, &old_sg); - - /* Due to a bug in Unix, fclose closes not only the stdio stream, - but also the file descriptor. So we don't actually close - st2000_desc. */ - if (st2000_stream) - fclose (st2000_stream); /* This also closes st2000_desc */ - - /* Do not try to close st2000_desc again, later in the program. */ - st2000_stream = NULL; - st2000_desc = -1; + serial_close(); #if defined (LOG_FILE) if (log_file) { - if (ferror (log_file)) - printf ("Error writing log file.\n"); - if (fclose (log_file) != 0) - printf ("Error closing log file.\n"); + if (ferror(log_file)) + fprintf(stderr, "Error writing log file.\n"); + if (fclose(log_file) != 0) + fprintf(stderr, "Error closing log file.\n"); } #endif } @@ -471,13 +358,13 @@ st2000_resume (step, sig) { printf_stdebug ("ST\r"); /* Wait for the echo. */ - expect ("ST\r"); + expect ("ST\r", 1); } else { printf_stdebug ("GO\r"); /* Swallow the echo. */ - expect ("GO\r"); + expect ("GO\r", 1); } } @@ -488,56 +375,16 @@ static int st2000_wait (status) WAITTYPE *status; { - /* FIXME --- USE A REAL STRING MATCHING ALGORITHM HERE!!! */ - - static char bpt[] = "dbug> "; - char *bp = bpt; - - /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */ - char swallowed[50]; - /* Current position in swallowed. */ - char *swallowed_p = swallowed; - - int ch; - int ch_handled; - int old_timeout = timeout; WSETEXIT ((*status), 0); timeout = 0; /* Don't time out -- user program is running. */ - while (1) - { - ch_handled = 0; - ch = readchar (); - if (ch == *bp) - { - bp++; - if (*bp == '\0') - break; - ch_handled = 1; - *swallowed_p++ = ch; - } - else - bp = bpt; + expect_prompt(0); /* Wait for prompt, outputting extraneous text */ + + WSETSTOP ((*status), SIGTRAP); - if (!ch_handled) - { - char *p; - - /* Print out any characters which have been swallowed. */ - for (p = swallowed; p < swallowed_p; ++p) - putc (*p, stdout); - swallowed_p = swallowed; - - putc (ch, stdout); - } - } - if (*bp == '\000') - WSETSTOP ((*status), SIGTRAP); - else - WSETEXIT ((*status), 0); timeout = old_timeout; return 0; @@ -589,10 +436,10 @@ st2000_fetch_register (regno) { char *name = get_reg_name (regno); printf_stdebug ("DR %s\r", name); - expect (name); - expect (" : "); + expect (name, 1); + expect (" : ", 1); get_hex_regs (1, regno); - expect_prompt (); + expect_prompt (1); } return; } @@ -623,7 +470,7 @@ st2000_store_register (regno) printf_stdebug ("PR %s %x\r", get_reg_name (regno), read_register (regno)); - expect_prompt (); + expect_prompt (1); } } @@ -659,7 +506,7 @@ st2000_write_inferior_memory (memaddr, myaddr, len) for (i = 0; i < len; i++) { printf_stdebug ("PM.B %x %x\r", memaddr + i, myaddr[i]); - expect_prompt (); + expect_prompt (1); } return len; } @@ -708,12 +555,12 @@ st2000_read_inferior_memory(memaddr, myaddr, len) len_this_pass = (len - count); printf_stdebug ("DI.L %x %x\r", startaddr, len_this_pass); - expect (": "); + expect (": ", 1); for (i = 0; i < len_this_pass; i++) get_hex_byte (&myaddr[count++]); - expect_prompt (); + expect_prompt (1); startaddr += len_this_pass; } @@ -775,7 +622,7 @@ st2000_insert_breakpoint (addr, shadow) st2000_read_inferior_memory(addr, shadow, memory_breakpoint_size); printf_stdebug("BR %x H\r", addr); - expect_prompt(); + expect_prompt(1); return 0; } @@ -796,7 +643,7 @@ st2000_remove_breakpoint (addr, shadow) breakaddr[i] = 0; printf_stdebug("CB %d\r", i); - expect_prompt(); + expect_prompt(1); return 0; } @@ -804,34 +651,170 @@ st2000_remove_breakpoint (addr, shadow) return 1; } + +/* Put a command string, in args, out to STDBUG. Output from STDBUG is placed + on the users terminal until the prompt is seen. */ + +static void +st2000_command (args, fromtty) + char *args; + int fromtty; +{ + if (st2000_desc < 0) + error("st2000 target not open."); + + if (!args) + error("Missing command."); + + printf_stdebug("%s\r", args); + expect_prompt(0); +} + +/* Connect the user directly to STDBUG. This command acts just like the + 'cu' or 'tip' command. Use ~. or ~^D to break out. */ + +static struct ttystate ttystate; + +static void +cleanup_tty() +{ + printf("\r\n[Exiting connect mode]\r\n"); + serial_restore(0, &ttystate); +} + +static void +connect_command (args, fromtty) + char *args; + int fromtty; +{ + fd_set readfds; + int numfds; + int c; + char cur_esc = 0; + + dont_repeat(); + + if (st2000_desc < 0) + error("st2000 target not open."); + + if (args) + fprintf("This command takes no args. They have been ignored.\n"); + + printf("[Entering connect mode. Use ~. or ~^D to escape]\n"); + + serial_raw(0, &ttystate); + + make_cleanup(cleanup_tty, 0); + + FD_ZERO(&readfds); + + while (1) + { + do + { + FD_SET(0, &readfds); + FD_SET(st2000_desc, &readfds); + numfds = select(sizeof(readfds)*8, &readfds, 0, 0, 0); + } + while (numfds == 0); + + if (numfds < 0) + perror_with_name("select"); + + if (FD_ISSET(0, &readfds)) + { /* tty input, send to stdebug */ + c = getchar(); + if (c < 0) + perror_with_name("connect"); + + printf_stdebug("%c", c); + switch (cur_esc) + { + case 0: + if (c == '\r') + cur_esc = c; + break; + case '\r': + if (c == '~') + cur_esc = c; + else + cur_esc = 0; + break; + case '~': + if (c == '.' || c == '\004') + return; + else + cur_esc = 0; + } + } + + if (FD_ISSET(st2000_desc, &readfds)) + { + while (1) + { + c = readchar(0); + if (c < 0) + break; + putchar(c); + } + fflush(stdout); + } + } +} + /* Define the target subroutine names */ -static struct target_ops st2000_ops = { - "st2000", "Remote serial Tandem ST2000 target", - "Use a remote computer running STDEBUG connected by a serial line,\n\ +struct target_ops st2000_ops = { + "st2000", + "Remote serial Tandem ST2000 target", + "Use a remote computer running STDEBUG connected by a serial line,\n\ or a network connection.\n\ Arguments are the name of the device for the serial line,\n\ the speed to connect at in bits per second.", - st2000_open, st2000_close, - 0, st2000_detach, st2000_resume, st2000_wait, - st2000_fetch_register, st2000_store_register, - st2000_prepare_to_store, 0, 0, /* conv_to, conv_from */ - st2000_xfer_inferior_memory, st2000_files_info, - st2000_insert_breakpoint, st2000_remove_breakpoint, /* Breakpoints */ - 0, 0, 0, 0, 0, /* Terminal handling */ - st2000_kill, - 0, /* load */ - 0, /* lookup_symbol */ - st2000_create_inferior, - st2000_mourn_inferior, - process_stratum, 0, /* next */ - 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */ - 0, 0, /* Section pointers */ - OPS_MAGIC, /* Always the last thing */ + st2000_open, + st2000_close, + 0, + st2000_detach, + st2000_resume, + st2000_wait, + st2000_fetch_register, + st2000_store_register, + st2000_prepare_to_store, + 0, + 0, /* conv_to, conv_from */ + st2000_xfer_inferior_memory, + st2000_files_info, + st2000_insert_breakpoint, + st2000_remove_breakpoint, /* Breakpoints */ + 0, + 0, + 0, + 0, + 0, /* Terminal handling */ + st2000_kill, + 0, /* load */ + 0, /* lookup_symbol */ + st2000_create_inferior, + st2000_mourn_inferior, + process_stratum, + 0, /* next */ + 1, + 1, + 1, + 1, + 1, /* all mem, mem, stack, regs, exec */ + 0, + 0, /* Section pointers */ + OPS_MAGIC, /* Always the last thing */ }; void _initialize_remote_st2000 () { add_target (&st2000_ops); + add_com ("st2000 ", class_obscure, st2000_command, + "Send a command to the STDBUG monitor."); + add_com ("connect", class_obscure, connect_command, + "Connect the terminal directly up to the STDBUG command monitor.\n\ +Use ~. or ~^D to break out."); } diff --git a/gdb/ser-bsd.c b/gdb/ser-bsd.c new file mode 100644 index 00000000000..6479ba16567 --- /dev/null +++ b/gdb/ser-bsd.c @@ -0,0 +1,228 @@ +/* Remote serial interface for OS's with sgttyb + Copyright 1992 Free Software Foundation, Inc. + +This file is part of GDB. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include "defs.h" +#include +#include +#include +#include "serial.h" + +static int desc = -1; + +void +serial_raw(fd, oldstate) + int fd; + struct ttystate *oldstate; +{ + struct sgttyb sgttyb; + + oldstate->flags = fcntl(fd, F_GETFL, 0); + + fcntl(fd, F_SETFL, oldstate->flags|FNDELAY); + + if (ioctl(fd, TIOCGETP, &sgttyb)) + { + fprintf(stderr, "TIOCGETP failed: %s\n", safe_strerror(errno)); + } + + oldstate->sgttyb = sgttyb; + + sgttyb.sg_flags = RAW; + + if (ioctl(fd, TIOCSETP, &sgttyb)) + { + fprintf(stderr, "TIOCSETP failed: %s\n", safe_strerror(errno)); + } +} + +void +serial_restore(fd, oldstate) + int fd; + struct ttystate *oldstate; +{ + fcntl(fd, F_SETFL, oldstate->flags); + + ioctl(fd, TIOCSETP, &oldstate->sgttyb); +} + +static struct ttystate oldstate; + +static fd_set readfds; + +int +serial_open(name) + char *name; +{ + struct sgttyb sgttyb; + + desc = open (name, O_RDWR); + if (desc < 0) + error("Open of %s failed: %s", name, safe_strerror(errno)); + + serial_raw(desc, &oldstate); + +/* Setup constant stuff for select */ + + FD_ZERO(&readfds); + + return desc; +} + +/* Read a character with user-specified timeout. TIMEOUT is number of seconds + to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns + char if successful. Returns -2 if timeout expired, EOF if line dropped + dead, or -3 for any other error (see errno in that case). */ + +int +serial_readchar(timeout) + int timeout; +{ + static unsigned char buf[BUFSIZ]; + static unsigned char *bufp; + static int bufcnt = 0; + int numfds; + struct timeval tv; + + if (bufcnt-- > 0) + return *bufp++; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + FD_SET(desc, &readfds); + + if (timeout >= 0) + numfds = select(desc+1, &readfds, 0, 0, &tv); + else + numfds = select(desc+1, &readfds, 0, 0, 0); + + if (numfds <= 0) + if (numfds == 0) + return -2; /* Timeout */ + else + return -3; /* Got an error from select */ + + bufcnt = read(desc, buf, BUFSIZ); + + if (bufcnt <= 0) + if (bufcnt == 0) + return EOF; /* 0 chars means end of file */ + else + return -3; /* Got an error from read */ + + bufcnt--; + bufp = buf; + return *bufp++; +} + +#ifndef B19200 +#define B19200 EXTA +#endif + +#ifndef B38400 +#define B38400 EXTB +#endif + +/* Translate baud rates from integers to damn B_codes. Unix should + have outgrown this crap years ago, but even POSIX wouldn't buck it. */ + +static struct +{ + int rate; + int code; +} baudtab[] = { + {50, B50}, + {75, B75}, + {110, B110}, + {134, B134}, + {150, B150}, + {200, B200}, + {300, B300}, + {600, B600}, + {1200, B1200}, + {1800, B1800}, + {2400, B2400}, + {4800, B4800}, + {9600, B9600}, + {19200, B19200}, + {38400, B38400}, + {-1, -1}, +}; + +static int +rate_to_code(rate) + int rate; +{ + int i; + + for (i = 0; baudtab[i].rate != -1; i++) + if (rate == baudtab[i].rate) + return baudtab[i].code; + + return -1; +} + +int +serial_setbaudrate(rate) + int rate; +{ + struct sgttyb sgttyb; + + if (ioctl(desc, TIOCGETP, &sgttyb)) + error("TIOCGETP failed: %s\n", safe_strerror(errno)); + + sgttyb.sg_ospeed = rate_to_code(rate); + sgttyb.sg_ispeed = rate_to_code(rate); + + if (ioctl(desc, TIOCSETP, &sgttyb)) + error("TIOCSETP failed: %s\n", safe_strerror(errno)); + + return 1; +} + +int +serial_write(str, len) + char *str; + int len; +{ + int cc; + + while (len > 0) + { + cc = write(desc, str, len); + + if (cc < 0) + return 0; + len -= cc; + str += cc; + } + return 1; +} + +void +serial_close() +{ + if (desc < 0) + return; + + serial_restore(desc, oldstate); + + close(desc); + desc = -1; +} diff --git a/gdb/ser-termios.c b/gdb/ser-termios.c index 357c2e80cf8..0a11f08229e 100644 --- a/gdb/ser-termios.c +++ b/gdb/ser-termios.c @@ -18,192 +18,206 @@ along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "defs.h" -#include "serial.h" #include -#include #include +#include "serial.h" -/* File descriptor used in termios routines to access serial line. */ -static int desc; - -/* Saved state about the terminal. */ -static struct termios otermios; -static int oflags; - -const char * -serial_default_name () -{ - return "/dev/ttya"; -} +static int desc = -1; void -serial_raw () +serial_raw(fd, oldstate) + int fd; + struct ttystate *oldstate; { - /* Now happens inside of serial_open */ + struct termios termios; + + oldstate->flags = fcntl(fd, F_GETFL, 0); + + fcntl(fd, F_SETFL, oldstate->flags|FNDELAY); + + if (tcgetattr(fd, &termios)) + { + fprintf(stderr, "tcgetattr failed: %s\n", safe_strerror(errno)); + } + + oldstate->termios = termios; + + termios.c_iflag = 0; + termios.c_oflag = 0; + termios.c_lflag = 0; + termios.c_cc[VMIN] = 0; + termios.c_cc[VTIME] = 0; + + if (tcsetattr(fd, TCSANOW, &termios)) + { + fprintf(stderr, "tcsetattr failed: %s\n", safe_strerror(errno)); + } } void -serial_normal () +serial_restore(fd, oldstate) + int fd; + struct ttystate *oldstate; { - fcntl(desc, oflags, 0); + fcntl(fd, F_SETFL, oldstate->flags); - if (tcsetattr(desc, TCSANOW, &otermios)) - { - printf("tcgetattr failed: errno=%d\n", errno); - } + tcsetattr(fd, TCSANOW, &oldstate->termios); } +static struct ttystate oldstate; + +static fd_set readfds; + int -serial_open (name) - const char *name; +serial_open(name) + char *name; { struct termios termios; desc = open (name, O_RDWR); if (desc < 0) - perror("Open failed: "); - - oflags = fcntl(desc, F_GETFL, 0); - - fcntl(desc, F_SETFL, oflags|FNDELAY); + error("Open of %s failed: %s", name, safe_strerror(errno)); - if (tcgetattr(desc, &termios)) { - printf("tcgetattr failed: errno=%d\n", errno); - } + serial_raw(desc, &oldstate); - otermios = termios; +/* Setup constant stuff for select */ - termios.c_iflag = 0; - termios.c_oflag = 0; - termios.c_lflag = 0; - termios.c_cc[VMIN] = 0; - termios.c_cc[VTIME] = 0; - - if (tcsetattr(desc, TCSANOW, &termios)) { - printf("tcgetattr failed: errno=%d\n", errno); - } + FD_ZERO(&readfds); - return 1; + return desc; } +/* Read a character with user-specified timeout. TIMEOUT is number of seconds + to wait, or -1 to wait forever. Use timeout of 0 to effect a poll. Returns + char if successful. Returns -2 if timeout expired, EOF if line dropped + dead, or -3 for any other error (see errno in that case). */ + int -serial_timedreadchar (timeout, ok) - int timeout; - int *ok; +serial_readchar(timeout) + int timeout; { - unsigned char buf; - fd_set readfds; - int val; + static unsigned char buf[BUFSIZ]; + static unsigned char *bufp; + static int bufcnt = 0; + int numfds; struct timeval tv; - FD_ZERO(&readfds); - FD_SET(desc, &readfds); + if (bufcnt-- > 0) + return *bufp++; tv.tv_sec = timeout; tv.tv_usec = 0; - val = select(desc+1, &readfds, 0, 0, &tv); + FD_SET(desc, &readfds); - if (val > 0 && FD_ISSET(desc, &readfds)) - { - val = read (desc, &buf, 1); + if (timeout >= 0) + numfds = select(desc+1, &readfds, 0, 0, &tv); + else + numfds = select(desc+1, &readfds, 0, 0, 0); - if (val == 1) - { - *ok = 1; - return buf; - } - } + if (numfds <= 0) + if (numfds == 0) + return -2; /* Timeout */ + else + return -3; /* Got an error from select */ + + bufcnt = read(desc, buf, BUFSIZ); - *ok = 0; + if (bufcnt <= 0) + if (bufcnt == 0) + return EOF; /* 0 chars means end of file */ + else + return -3; /* Got an error from read */ - return 0; + bufcnt--; + bufp = buf; + return *bufp++; } /* Translate baud rates from integers to damn B_codes. Unix should have outgrown this crap years ago, but even POSIX wouldn't buck it. */ -#ifndef B19200 -#define B19200 EXTA -#endif -#ifndef B38400 -#define B38400 EXTB -#endif - -static struct {int rate, damn_b;} baudtab[] = { - {9600, B9600}, - - {19200, B19200}, - {38400, B38400}, -#if 0 - {300, B300}, - {1200, B1200}, - {2400, B2400}, - {4800, B4800}, -#endif - {-1, -1}, +static struct +{ + int rate; + int code; +} baudtab[] = { + {50, B50}, + {75, B75}, + {110, B110}, + {134, B134}, + {150, B150}, + {200, B200}, + {300, B300}, + {600, B600}, + {1200, B1200}, + {1800, B1800}, + {2400, B2400}, + {4800, B4800}, + {9600, B9600}, + {19200, B19200}, + {38400, B38400}, + {-1, -1}, }; static int -damn_b (rate) - int rate; +rate_to_code(rate) + int rate; { int i; + for (i = 0; baudtab[i].rate != -1; i++) - { if (rate == baudtab[i].rate) - { - return i; - } - } + return baudtab[i].code; + return -1; } -int -serial_setbaudrate (rate) +int +serial_setbaudrate(rate) int rate; { struct termios termios; - if (tcgetattr(desc, &termios)) { - printf("tcgetattr failed: errno=%d\n", errno); - } + if (tcgetattr(desc, &termios)) + error("tcgetattr failed: %s\n", safe_strerror(errno)); - cfsetospeed(&termios, baudtab[damn_b(rate)].damn_b); - cfsetispeed(&termios, baudtab[damn_b(rate)].damn_b); + cfsetospeed(&termios, rate_to_code(rate)); + cfsetispeed(&termios, rate_to_code(rate)); - if (tcsetattr(desc, TCSANOW, &termios)) { - printf("tcgetattr failed: errno=%d\n", errno); - } + if (tcsetattr(desc, TCSANOW, &termios)) + error("tcsetattr failed: %s\n", safe_strerror(errno)); return 1; } int -serial_nextbaudrate (rate) - int rate; +serial_write(str, len) + char *str; + int len; { - int lookup; - lookup = damn_b(rate); - if (lookup == -1) - return baudtab[0].rate; - lookup++; - if (baudtab[lookup].rate == -1) - return baudtab[0].rate; - return baudtab[lookup].rate; + int cc; + + while (len > 0) + { + cc = write(desc, str, len); + + if (cc < 0) + return 0; + len -= cc; + str += cc; + } + return 1; } -int -serial_write (str, len) - const char *str; - int len; +void +serial_close() { - return (write (desc, str, len)); -} + if (desc < 0) + return; + serial_restore(desc, oldstate); -int -serial_close () -{ - return (close(desc)); + close(desc); + desc = -1; } diff --git a/gdb/serial.h b/gdb/serial.h index f56041829c6..2944bb66cea 100644 --- a/gdb/serial.h +++ b/gdb/serial.h @@ -42,16 +42,37 @@ int serial_timedreadchar PARAMS ((int to, int *ok)); /* Set the baudrate to the decimal value supplied, and return 1, or fail and return 0. */ -int serial_setbaudrate PARAMS ((int to)); +int serial_setbaudrate PARAMS ((int rate)); /* Return the next rate in the sequence, or return 0 for failure. */ -int serial_nextbaudrate PARAMS ((int rate)); +/* Write some chars to the device, returns 0 for failure. See errno for + details. */ -/* Write some chars to the device, return 1 if ok, 0 if not. */ +int serial_write PARAMS ((const char *str , int len)); -int serial_write PARAMS ((const char *str, int len)); +/* Close the serial port */ -/* Close the serial port. */ +void serial_close PARAMS ((void)); -int serial_close PARAMS ((void)); +#ifdef HAVE_TERMIO + +#include +#include + +struct ttystate +{ + int flags; /* Flags from fcntl F_GETFL */ + struct termios termios; /* old tty driver settings */ +}; + +#else /* not HAVE_TERMIO */ + +#include + +struct ttystate { + int flags; /* Flags from fcntl F_GETFL */ + struct sgttyb sgttyb; /* old tty driver settings */ +}; + +#endif /* not HAVE_TERMIO */ diff --git a/gdb/xm-apollo68b.h b/gdb/xm-apollo68b.h index aa4375eacc3..0c0e14f8b85 100755 --- a/gdb/xm-apollo68b.h +++ b/gdb/xm-apollo68b.h @@ -22,3 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ALIGN_STACK_ON_STARTUP #define FETCH_INFERIOR_REGISTERS + +#define PTRACE_IN_WRONG_PLACE + +extern char *strdup(); -- 2.30.2